I come from a Java background and I am learning Objective C. I am trying to create a class that has a string array and a member function to modify the Array. My code looked like this:
@implementation TAWChapter
@synthesize mSubject;
@synthesize mItems;
- (id) init{
self.mItems = [[NSMutableArray alloc] init];
return self;
}
- (void) setSubject:(NSString *)subject{
self.mSubject = subject;
}
- (void) addItem:(NSString *)item{
[self.mItems addObject:@"asdf"];
}
@end
Which didn't work. I got a "[__NSArrayI addObject:]: unrecognized selector sent to instance "
and a "NSInvalidArgumentException"
. After searching on internet, I changed the single line in the constructor to:
self.mItems = [self.mItems init];
It worked, but why? From a Java developer's point of view the first one makes more sense than the second one. And I have another line it's the same as the first one but it's working(not in a constructor). Can someone explain this to me please?
Since objective-c is a superset of c, it's basically c with some "OO" syntax sugar. Before you can create (or use!) an object, you must alloc space for it in the heap. you do this with [Class alloc]
. The next step is the initialization of that space. alloc returns a pointer to that space in the heap, which you initialize with init ;)
So you call Class *myObjc = [[Class alloc] init];
.
If you use inheritance (which you do since you inherit from NSOBject), you must make sure that your superclass initialized everything properly, thats the call to super. To make sure you don't get a runtime error, check for self != nil, which you do implicitly with if(self)
self.mItems = [self.mItems init]; // doesn't do anything, since you call the getter for mItems with self.mItems and try to init. then you try to set mItmes to itself.
use this code:
@implementation TAWChapter
@synthesize mSubject, mItems;
- (id)init
{
self = [super init];
if (self) {
mItems = [[NSMutableArray alloc] init];
}
return self;
}
- (void) setSubject:(NSString *)subject{
mSubject = subject;
}
- (void) addItem:(NSString *)item{
[mItems addObject:item];
}
@end
You should call super
and assign its result to self
in your init
method:
- (id)init
{
self = [super init];
if (self) {
self.mItems = [[NSMutableArray alloc] init];
}
return self;
}
The another way could be creating NSMutableArray from NSArray:
NSMutableArray *myMutableArray = [NSMutableArray arrayWithArray:myArray];