I've got a very basic example where I'm reading some data into a class from JSON, and my objects are getting corrupted somehow. I suspect I'm missing some detail about how properties/ARC is working, but I'm not sure what it is, or how I'd track it down.
I've reduced my original code so that the problem is obvious. However this means that its not clear why I'm using custom properties etc. - my real code has more functionality in there...
The issue can be seen in the last line of the Test.m file. The first constructed object now contains data from the second object rather than the value it originally contained.
Any advice on what I'm doing wrong and/or how to track down this kind of issue would be greatly appreciated.
ANBNote.h
@interface ANBNote : NSObject
@property (nonatomic,readwrite) NSArray* references;
- (id)initWithJson:(NSDictionary*)data;
@end
ANBNote.m
#import "ANBNote.h"
@implementation ANBNote
NSArray * _references;
-(id) init {
if(!(self=[super init])) return nil;
_references=@[];
return self;
}
-(id)initWithJson:(NSDictionary *)jsonObject {
if(!(self = [self init] ) ) { return nil; }
_references = jsonObject[@"references"];
return self;
}
-(void) setReferences:(NSArray *)references {
_references = references;
}
-(NSArray *)references {
return _references;
}
@end
Test.m
...
NSDictionary * d1 = @{@"references":@[@"r1",@"r2"]};
NSDictionary * d2 = @{@"references":@[@"q1",@"q2"]};
ANBNote * n1 = [[ANBNote alloc] initWithJson:d1];
NSLog(@"R1 = %p, %@", n1.references, n1.references); // Prints r1, r2 - as expected
ANBNote * n2 = [[ANBNote alloc] initWithJson:d2];
NSLog(@"R2 = %p, %@", n2.references, n2.references); // Prints q1, q2 - as expected
NSLog(@"R1 = %p, %@", n1.references, n1.references); // Prints q1, q2 - Oh No!
Note that if I remove custom references property functions and rely on the compiler generated version everything seems to behave correctly.
This is not the root of yout problem but change your
initWithJson:
toDitch the custom setter and getter (you obviously don't need them).
In your case you can declare property simply with:
Change the
NSArray * _references;
to:You can also omit the
@synthesize
line in your case.Also change
_references = jsonObject[@"references"];
to:To sum it all together:
ANBNote.h
ANBNote.m
This is not a ivar:
it's a global. There's only one for all the instances of your class, not one for each. When the next instance sets it, the previous instances see the new values because it's the same variable. You need to put it into curly braces to make it an ivar:
There's no need to declare the variable explicitly, though -- you can still implement accessors yourself and let the compiler create the ivar as long as you use the default synthesized name (underscore + property name).
The answer is simple, you defined NSArray *_references as a static variable not as a private variable. To do that
In addition to this as of Xcode 4 you do not have to define _references object in the implementation file. You may just set a variable in the header file and then access its private accessor by just typing
_
before the name of it.For instance