Reputation: 14553
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.
Upvotes: 0
Views: 1208
Reputation: 5558
@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.
Upvotes: 3
Reputation: 6176
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
Upvotes: 1
Reputation: 5681
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];
Upvotes: 0
Reputation: 24481
Casting won't work in this case. You need to change your property to an NSMutableArray:
@property (nonatomic, copy) NSMutableArray *toolbarButtons;
Upvotes: 0