2011-02-03 3 views
5

SomeObject가 @property (nonatomic, retain)로 작성된 클래스 속성 인 경우 someObject = someOtherObject;self.someObject = someOtherObject; 사이의 차이점을 설명 할 수 있습니까 SomeType someObject; 내가 자기없이 속성을 사용할 때 가끔 EXC_BAD ACCESS를 얻고 꽤 무작위로 보인다 발견했습니다언제 자기와 함께 부동산에 액세스 할 수 있습니까?

@interface SomeClass : NSObject { 
    SomeType* someObject; 
} 

@property (nonatomic, retain) SomeType* someObject; 

@end 

:

는 내가 좋아하는 뭔가를 명확히하기 위해. 자기를 사용할 때 프로그램이 있어야하는 것처럼 행동합니다. 나는 어떤 식 으로든 유효한 문법이라고 생각한다. 그래서 나는 스스로를 건너 뛸 때 컴파일러 에러 나 경고를 얻지 못한다.

+0

가능한 경우 [self 키워드를 사용해야합니까?] (http://stackoverflow.com/questions/4080523/when-should-i-use-the-self-keyword) 이것은 매우 자주 묻는 질문입니다. 질문하기 전에 찾으십니까? – zoul

답변

2

속성은 데이터에 액세스하는 편리한 방법입니다. 그래서 당신이 속성을 선언 할 때 @property (nonatomic, retain) SomeType * someObject; 이는 액세스시의 2 가지 방법이 합성 될 수 있다는 것을 의미 :

게터 :

-(SomeType*) someObject { 
    return someObject; 
} 

세터

-(void) setSomeObject:(SomeType*) obj { 
    [someObject release]; 
    someObject = [obj retain]; 
} 

따라서 속성과 인스턴스 변수 사이의 주요 차이는 특성 동적 세터/게터를 생성한다는 것이다 메서드 (및 재정의 할 수 있습니다). 그러나 someObject = new_val을 작성할 때 참조를 메모리 위치에 복사하는 것입니다. 하나의 어셈블리 명령을 제외하고는 추가 작업이 수행되지 않습니다.

언급해야 할 것이 하나 더 있습니다. 원자 및 비 원자가 있습니다. 원자를 사용하면 합성 된 setter/getter는 다른 스레드의 setter 활동에 관계없이 항상 getter에서 전체 값이 반환되거나 setter에 의해 설정되도록합니다. 즉, thread A가 getter의 중간에 thread B가 setter를 호출하고있는 경우, 실제로 실행 가능한 값, 즉 자동 회수 된 객체가 A의 호출 측에 돌려 주어집니다.

비 원자형의 경우, 그러한 보장은 없다. 따라서 비 원자가 원자보다 상당히 빠릅니다.

편집 : 다른 스레드에서 액세스하거나 일부 추가 작업을 수행해야하는 변수가있는 경우 (예 : 보유, 일부 플래그 발생 ...), 선택 사항은 속성입니다. 그러나 종종 프로세서에 합성 및 호출 방법을 더 많이 수행해야하기 때문에 매우 자주 액세스되는 속성을 통해 액세스하면 큰 오버 헤드가 발생할 수있는 변수가 있습니다.

4

self.someObject = someOtherObject은 해당 부동산을 사용하고 있습니다. 속성은 setter 및 getter를 생성합니다. 귀하의 경우, 속성에 retain 속성을 지정 했으므로이 속성을 통해 설정된 객체는 자동으로 retain 메시지를 수신하여 보유 수를 1 씩 증가시킵니다. 또한 구성원 변수의 이전 값은 release 메시지로 전송됩니다 보유 수를 감소시킵니다.

보존 개수가 0에 도달하면 할당이 해제됩니다. 할당 해제 된 개체에 액세스하려고하면 EXC_BAD_ACCESS 환경이 표시됩니다 (예 : 너무 자주 해제하려고 시도하는 경우). 귀하의 경우에는

: 당신이 세터를 사용하지 않는 경우

SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1 
self.someObject = soo; //soo's retain count is now 2 
[soo release]; //soo's retain count is 1 again, as self still uses it. 
[self doSomethingWithSoo]; 

그러나, 당신은 soo를 공개하지해야합니다.

SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1 
someObject = soo; //soo's retain count is still 1 
[soo release]; //soo's retain count is 0, it will be deallocated 
[self doSomethingWithSoo]; //will fail with an EXC_BAD_ACCESS exception, as soo does not exist anymore. 
0

둘 사이의 차이는 다음과 같습니다

1) 사용하지 않는 경우 "자기를." 결과를 멤버 변수에 직접 할당합니다.

2) "자기"를 사용하는 경우 그 속성에 setter 메서드를 호출하고 있습니다. 이것은 [self setMyObject : ...]와 동일합니다.

그래서 self.myobject의 경우에는 retain을 유지하고 다른 경우에는 (자기없이) alloc을 사용하지 않으면 autoreleased object로 처리됩니다.

대부분의 경우 개체 초기화 중을 제외하고 "self."를 사용하게됩니다. 그런데

, 당신은 또한 그것은 모든 메모리 관리에 관하여 카운터

1

을 유지 증가 self.someObject = [someOtherObject retain]를 사용할 수 있습니다.

클래스 속성 someObject은 .h/.m 파일에 @property/@synthsize이라는 특수 효과가있는 접근자를 생성했습니다.

someObject으로 속성에 액세스하면 속성에 직접 액세스 할 수 있습니다. self.someObject에 액세스 할 때 액세서 [self someObject]을 호출하면 메모리 관리를 담당합니다.

클래스 속성을 지정할 필요가있을 때 self.someObject = someOtherObject;을 수행하는 것이 더 깔끔하고 설정자를 사용하고 해제 및 유지에 신경을 쓸 필요가 없기 때문에. 당신의 세터가 @property (nonatomic, retain)으로 생성 될 때, 당신을 위해 유지에주의를 기울일 것입니다.

관련 문제