2013-08-17 2 views
2

JSON에서 클래스로 일부 데이터를 읽는 아주 기본적인 예제가 있는데 내 오브젝트가 어떻게 든 손상됩니다. 나는 속성/ARC가 어떻게 작동하는지에 대한 세부 사항을 놓치고 있다고 생각하지만, 그것이 무엇인지, 또는 그것을 추적 할 방법이 확실하지 않다.내 개체가 예기치 않게 변경되는 이유는 무엇입니까?

문제가 분명하도록 원본 코드가 축소되었습니다. 그러나 이것은 왜 내가 사용자 정의 속성 등을 사용하고 있는지 명확하지 않다는 것을 의미합니다. 실제 코드에 더 많은 기능이 있습니다.

문제는 Test.m 파일의 마지막 줄에서 볼 수 있습니다. 첫 x 째 구성된 오브젝트에는 원래 포함 된 값이 아닌 두 x 째 오브젝트의 데이터가 포함됩니다.

내가 뭘 잘못하고 있는지에 대한 조언이나이 문제를 추적하는 방법에 대한 조언은 크게 감사하겠습니다.

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; 
    [email protected][]; 
    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! 

주 내가 CUST를 제거하는 경우 있음 옴은 속성 함수를 참조하고 모든 것이 올바르게 작동하는 것으로 보이는 컴파일러 생성 버전에 의존합니다. 그것은 세계의

@implementation ANBNote 
NSArray * _references; 

:

답변

2

이는 바르 없습니다. 각 클래스 인스턴스에는 하나만 존재하지 않습니다. 다음 인스턴스가 그것을 설정할 때 이전 인스턴스는 동일한 변수이기 때문에 새 값을 보게됩니다. 당신은 여전히 ​​접근을 직접 구현하고 컴파일러가 당신만큼 오랫동안 바르를 만들 수 있습니다 -하지만, 명시 적으로 변수를 선언 할 필요가 없습니다

@implementation ANBNote 
{ 
    NSArray * _references; 
} 

: 당신은 그에게 바르를 만들기 위해 괄호에 넣어 필요 합성 된 기본 이름 (밑줄 + 속성 이름)을 사용하십시오.

+0

글로벌 vs ivars에 관한 문제가 있으며,'{}'을 사용하여 ivar로 추가하는 것이 효과적입니다. 그러나 ivar 정의를 제거하면 선언되지 않은 '_references'를 사용하게됩니다 ... –

+0

컴파일러가 자동 합성을 지원해서는 안됩니다. 정확한 버전에 따라 밑줄로 생성 된 ivar를 갖기 위해'@synthesize references; '를 할 수도 있고 (충분히 오래된 경우) 실제로 ivar을 별도로 선언 한 다음 '@synthesize references = _references;' –

+0

이 경우에는 ivar을 생략 할 수 없습니다. http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html " 참고 : ... readwrite 속성에 getter와 setter를 모두 구현하거나 readonly 속성에 getter를 구현하면 컴파일러는 속성 구현을 제어하고 인스턴스 변수를 자동으로 합성하지 않는다고 가정합니다. 여전히 인스턴스 변수가 필요한 경우 합성 변수를 요청해야합니다. '@synthesize property = _property;' " –

2

대답은 간단합니다. 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 
+0

static vs ivar 문제에 대해 살펴 보겠습니다. 그러나'@implementation {...}'섹션에서 정의를 제거하면'선언되지 않은 식별자 사용 _references; '오류가 발생합니다. 내가 놓친 게 있니? 다시 말해, 사용자 정의 getter/setter 함수를 정의하지 않는다면이 문제는 해결됩니다.하지만 실제 코드에서는 꼭 필요합니다. –

+0

사용자 정의 getter 및 setter를 설정하는 경우 -setReferences : (NSArray *) references {...} 및 get 메소드를 무시할 수 있습니다. NSArray * _references를 작성할 필요가 없습니다. 다시 구현합니다. Btw는 헤더 파일에 @property (strong, nonatomic) NSArray * 참조를 작성 했습니까? – kkocabiyik

+0

ivar 조언 누락이 잘못된 것처럼 보입니다. http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html "참고 : ... readwrite 속성에 getter와 setter를 모두 구현하거나 readonly 속성에 getter를 구현하면 컴파일러는 속성 구현을 제어하고 승리했다고 가정합니다. 인스턴스 변수를 자동으로 합성하지 않습니다. 여전히 인스턴스 변수가 필요한 경우 합성 변수를 요청해야합니다. '@synthesize property = _property;' " –

0

이 들어

이 행해져 Yout 문제의 근본이 아니라 당신의 initWithJson: 도랑

-(id)initWithJson:(NSDictionary *)jsonObject 
{  
    if(!(self = [super init])) { return nil; }  
    _references = jsonObject[@"references"];  
    return self; 
} 

에 사용자 정의 세터와 게터를 (당신은 분명 그들을 필요로하지 않음)로 변경합니다.귀하의 경우 단순히으로 속성을 선언 할 수 있습니다에서

:

@property (strong) NSArray* references; 

변경 NSArray * _references;에 :

@synthesize references = _references; 

당신은 또한 당신의 경우에 @synthesize 라인을 생략 할 수 있습니다. 모두 함께 정리해

_references = [NSArray arrayWithArray:jsonObject[@"references"]]; 

:

@interface ANBNote : NSObject 
@property (strong) NSArray* references; 
- (id)initWithJson:(NSDictionary*)data; 
@end 

ANBNote.m

ANBNote.h을

은 또한 변경

+0

의견을 보내 주셔서 감사합니다. "원래 코드를 줄여서 문제가 명백해 지도록했습니다. 그러나 이것이 내가 왜 c를 사용하는지 명확하지 않다는 것을 의미합니다. 사용자 정의 getter/setter를 사용하지 않는 것은 그 추가 기능으로 인해 나를위한 옵션이 아닙니다. –

관련 문제