我有一个非常基本的例子,我将一些数据从JSON读入一个类,我的对象以某种方式被破坏了。我怀疑我遗漏了一些关于属性/ ARC如何工作的细节,但我不确定它是什么,或者我如何追踪它。
我减少了原始代码,因此问题很明显。然而,这意味着我不清楚为什么我使用自定义属性等 - 我的真实代码在那里有更多的功能...
问题可以在Test.m文件的最后一行看到。第一个构造的对象现在包含来自第二个对象的数据,而不是它最初包含的值。
对于我做错了什么和/或如何追查这类问题的任何建议将不胜感激。
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!
请注意,如果我删除自定义引用属性函数并依赖编译器生成的版本,一切似乎都表现正常。
答案 0 :(得分:2)
这不是伊娃:
@implementation ANBNote
NSArray * _references;
它是全球性的。对于您班级的所有实例,只有一个,而不是每个实例。当下一个实例设置它时,之前的实例会看到新值,因为它是相同的变量。你需要将它放入花括号中以使其成为一个ivar:
@implementation ANBNote
{
NSArray * _references;
}
虽然没有必要明确声明变量 - 你仍然可以自己实现访问器,只要你使用默认的合成名称(下划线+属性名称),就让编译器创建ivar。
答案 1 :(得分:2)
答案很简单,您将NSArray * _references定义为静态变量而不是私有变量。要做到这一点
@implementation ANBNote{
NSArray * _references;
}
除了Xcode 4之外,您不必在实现文件中定义_references对象。您只需在头文件中设置一个变量,然后只需在其名称前键入_
即可访问其私有访问者。
例如
@interface ANBNote
@property(strong , nonatomic) NSArray *references;
@end
@implementation ANBNote
-(id) initWithArray:(NSArray *) ar{
if(self)
_references = [NSArray arrayWithArray:ar];
return self;
}
@end
答案 2 :(得分:0)
这不是问题的根源,而是将initWithJson:
更改为
-(id)initWithJson:(NSDictionary *)jsonObject
{
if(!(self = [super init] ) ) { return nil; }
_references = jsonObject[@"references"];
return self;
}
抛弃自定义setter和getter(你显然不需要它们)。
在您的情况下,您可以使用以下方式声明属性:
@property (strong) NSArray* references;
将NSArray * _references;
更改为:
@synthesize references = _references;
您也可以省略案例中的@synthesize
行。
同时将_references = jsonObject[@"references"];
更改为:
_references = [NSArray arrayWithArray:jsonObject[@"references"]];
总结一下:
<强> ANBNote.h 强>
@interface ANBNote : NSObject
@property (strong) NSArray* references;
- (id)initWithJson:(NSDictionary*)data;
@end
<强> ANBNote.m 强>
#import "ANBNote.h"
@implementation ANBNote
-(id) init {
if(!(self=[super init])) return nil;
_references=@[];
return self;
}
-(id)initWithJson:(NSDictionary *)jsonObject {
if(!(self = [super init] ) ) { return nil; }
_references = [NSArray arrayWithArray:jsonObject[@"references"]];
return self;
}
@end