简体   繁体   中英

Store NSMutableArray in NSArray?

I have a property an NSArray property called toolbarButtons that in one instance (when the UIViewController is modal) it needs to be an NSMutableArray , and when the UIViewController is nonmodal, it needs to simply be an NSArray .

I have initialized the property like this:

@property (nonatomic, copy) NSArray *toolbarButtons;

I am initializing toolbarButtons as follows:

- (void) setToolbarButtons 
{
        UIBarButtonItem *exitButton = [[UIBarButtonItem alloc] initWithTitle:@"Exit" style:UIBarButtonItemStyleBordered target:self action:@selector(exitButtonPushed)];

        toolbarButtonsTemp = (NSMutableArray *)[[NSMutableArray alloc] init];
        [(NSMutableArray*)toolbarButtonsTemp addObject:exitButton];
        self.toolbarButtons = toolbarButtonsTemp;

        [exitButton release]; 
}

Then later on I override the above method in a subclass like this:

- (void) setToolbarButtons 
{
    [super setToolbarButtons];

    UIBarButtonItem *leftFlexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    UIBarButtonItem *toolButton = [[UIBarButtonItem alloc] initWithTitle:@"Tools" style:UIBarButtonItemStyleBordered target:self action:@selector(toolButtonPushed)];

    [(NSMutableArray*)self.toolbarButtons addObject:leftFlexibleSpace];
    [(NSMutableArray*)self.toolbarButtons addObject:toolButton];

    [toolButton release];
    [leftFlexibleSpace release];
}

and I'm getting the following error:

[__NSArrayI addObject:]: unrecognized selector sent to instance

I know there are a ton of work arounds to this, but from a design perspective I'm just wondering if what I'm doing is possible and how to correct my mistake.

@property ( nonatomic, copy ) NSArray* array

means:

- (void) setArray: (NSArray*) array
{
    _array = [array copy];
}

[array copy] always returns an non mutable NSArray, even if array is a NSMutableArray.

@property ( nonatomic, copy ) NSMutableArray* array

is handled a bit differently:

- (void) setArray: (NSMutableArray*) array
{
    _array = [array mutableCopy];
}

In that case, you can do

self.array = (NSMutableArray*) [NSArray new];

and array will be assigned with a NSMutableArray, as mutableCopy always returns an NSMutableArray.

The latter is of course strongly discouraged. It works for now. No guarantee it will work forever.

Your other choice, besides an NSMutableArray, is to use a strong property and to handle the copies yourself.

you cannot do that!

when you:

 [(NSMutableArray*)self.toolbarButtons addObject:leftFlexibleSpace];
    [(NSMutableArray*)self.toolbarButtons addObject:toolButton];

you are just casting the property, it means you are promising in runtime that that property is a NSMutableArray... but you are lying!!!

i suggest you do the contrary: just declare it as a NSMutableArray (it's a subclass of NSArray, so you can use it as a NSArray when you want it),and use the NSMutableArray methods just when you need them

Casting won't work in this case. You need to change your property to an NSMutableArray:

@property (nonatomic, copy) NSMutableArray *toolbarButtons;

You should just use an NSMutableArray in your property, but you could always do something like this too...

 NSMutableArray *mutArray = [[NSMutableArray alloc] init];
    [mutaArray addObject:leftFlexibleSpace];
    [mutaArray addObject:toolButton];

    self.toolbarButtons = [NSArray arrayWithArray:mutArray];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM