I’m following the “Your Second iOS App” and I decided to play with the code to understand Objective C well…
What I’m trying to do is simply adding an object to a mutable array in a class. Here are the classes:
BirdSighting.h
#import <Foundation/Foundation.h>
@interface BirdSighting : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *location;
@property (nonatomic, copy) NSDate *date;
-(id) initWithName: (NSString *) name location:(NSString *) location date:(NSDate *) date;
@end
BirdSighting.m
#import "BirdSighting.h"
@implementation BirdSighting
-(id) initWithName:(NSString *)name location:(NSString *)location date:(NSDate *)date
{
self = [super init];
if(self) {
_name = name;
_location = location;
_date = date;
return self;
}
return nil;
}
@end
BirdSightingDataController.h
#import <Foundation/Foundation.h>
@class BirdSighting;
@interface BirdSightingDataController : NSObject
@property (nonatomic, copy) NSMutableArray *masterBirdSightingList;
- (NSUInteger) countOfList;
- (BirdSighting *) objectInListAtIndex: (NSUInteger) theIndex;
- (void) addBirdSightingWithSighting: (BirdSighting *) sighting;
@end
BirdSightingDataController.m
#import "BirdSightingDataController.h"
@implementation BirdSightingDataController
- (id) init {
if(self = [super init]) {
NSMutableArray *sightingList = [[NSMutableArray alloc] init];
self.masterBirdSightingList = sightingList;
return self;
}
return nil;
}
-(NSUInteger) countOfList
{
return [self.masterBirdSightingList count];
}
- (BirdSighting *) objectInListAtIndex: (NSUInteger) theIndex
{
return [self.masterBirdSightingList objectAtIndex:theIndex];
}
- (void) addBirdSightingWithSighting: (BirdSighting *) sighting
{
[self.masterBirdSightingList addObject:sighting];
}
@end
And this is where I’m trying to add a BirdSighting instance to the mutable array:
#import "BirdsMasterViewController.h"
#import "BirdsDetailViewController.h"
#import "BirdSightingDataController.h"
#import "BirdSighting.h"
@implementation BirdsMasterViewController
- (void)awakeFromNib
{
[super awakeFromNib];
BirdSightingDataController *dataController = [[BirdSightingDataController alloc] init];
NSDate *date = [NSDate date];
BirdSighting *sighting = [[[BirdSighting alloc] init] initWithName:@"Ebabil" location:@"Ankara" date: date];
[dataController addBirdSightingWithSighting: sighting];
NSLog(@"dataController: %@", dataController.masterBirdSightingList);
self.dataController = dataController;
}
..........
@end
It throws NSInvalidArgumentException in BirdSightingDataController addBirdSightingWithSighting method…
What am I doing wrong?
This is the full debug output:
2012-11-26 01:22:38.495 BirdWatching[4597:c07] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x71899d0
2012-11-26 01:22:38.496 BirdWatching[4597:c07] * Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[__NSArrayI addObject:]: unrecognized selector sent to instance 0x71899d0’
This line:
should be:
You can’t call two initializers.
Update:
Based on the complete error message I now see the problem. The
NSMutableArrayyou think you have for the property is really anNSArray. This is caused by defining the property withcopy.When you define
copyfor a property, it makes an immutable copy of the object. So when you assign yourNSMutableArray, an immutable copy is made and then assigned to the instance variable. So you end up assigning anNSArray, not anNSMutableArray.A fix is to change the property definition from:
to: