2012-12-13 4 views
1

ARC 라이브러리를 사용하는 비 ARC 프로젝트가 있습니다. 라이브러리 메서드에서 반환 된 객체를 해제해야하는지 혼란 스럽습니다. 여기에 몇 가지 예가 나와 있습니다 :비 ARC 코드에서 ARC 메소드 호출

- (void)test{ 
    LibObject* obj1 = [[LibObject alloc] init]; 
    LibObject* obj2 = [obj1 otherObj]; 

    [obj1 release]; //should I release it? 
    [obj2 release]; //should I release it? 
} 

객체가 자동 풀에 저장되어 있다면 잘 보관 해 두어야합니다. 그렇지 않으면, 나는 그것을 풀어야한다.

그러나, the ARC document는 모든 지역의 범위를 잎 한 다음 유지 밖으로 균형,

같은 함수 또는 메소드에서 반환 ARC는 return 문의 평가 지점의 값을 유지 말한다 이 값이 호출 경계를 넘어 서도록 보장합니다. 최악의 경우, 이것은 autorelease를 포함 할 수 있지만 호출자는 그 값이 실제로 autorelease 풀에 있다고 가정해서는 안됩니다.

문서는 자동 릴리스 된 것으로 가정 할 수 없으므로 항상 객체를 릴리스해야 함을 의미합니까?

답변

3

"고급 메모리 관리 프로그래밍 가이드"에 Memory Management Policy를 참조하십시오 : 당신은 어떤 객체를 소유

가 만든 당신은 이름이 "ALLOC"로 시작, "새로운 방법 를 사용하여 객체를 생성
","copy "또는"mutableCopy "(예 : 의 경우 alloc, newObject 또는 mutableCopy).

당신은 당신이

이 규칙은 ARC 컴파일 방법과 일치 소유하지 않은 오브젝트의 소유권을 포기하지 않아야합니다. ARC documentation에서 는 첫 번째 범주의 방법의 동작은 ". 3.2.2 보존 리턴 값"에 설명되어

이러한 함수 또는 메소드로부터 반환 ARC는 시점 값 유지 return 문 평가 ...

즉 호출자가 객체를 릴리스해야 함을 의미합니다. 두 번째 범주에서

방법은. "3.2.3 Unretained 리턴 값"에 설명되어

이러한 함수 또는 메소드로부터 반환 ARC는 반환 평가 지점에서의 값 유지 문은, 다음 ... 테인 밖으로 균형을 다음 개체를 해제하지해야합니다 발신자를 의미

모든 지역의 범위를 남겨두고,. 그래서 예에서

은 :이 alloc로 만들었 기 때문에

LibObject* obj1 = [[LibObject alloc] init]; 
LibObject* obj2 = [obj1 otherObj]; 
[obj1 release]; //should I release it? --> YES 
[obj2 release]; //should I release it? --> NO 

당신은 obj1 소유, 그래서 당신은 obj1를 해제해야합니다.

당신은 obj2을 소유하고 있지 않으므로 그것을 공개하면 안됩니다.

참고 : 코드에서 Xcode 정적 분석기를 실행하면 이러한 규칙을 위반 한 위치가 정확히 표시됩니다.

0

제 생각에이 파일에 컴파일러 플래그 -fno-objc-arc을 사용하면 자신을 유지/릴리스해야합니다. 따라서 [obj1 release]으로 전화하십시오. 직접 호출하지 않아도된다면 컴파일러는 그에 따라 경고합니다.

2

ARC가 활성화 된 클래스에서 ARC를 지원하지 않는 클래스로 객체를 가져 오는 경우 메모리를 관리해야합니다.

ARC는 컴파일 시간이 인 동안 ARC 사용 가능 코드에 retain, release를 입력하기 만하면됩니다. ARC 모드가 아닌 다른 클래스 나 객체의 메모리는 관리하지 않습니다.

필요에 따라 이러한 객체를 해제해야합니다.

0

제 생각에 비 ARC 코드에서는 항상 ARC 가능 라이브러리가있는 모든 유지/릴리스를 수행합니다 (다른 ARC 코드와 상호 작용하는 것처럼).

이 동작을 증명할 수있는 간단한 앱을 만들었습니다. ARC

- (void)testARC 
{ 
    ARCLib *al = [[ARCLib alloc] init]; 
    NSLog(@"%p retainCount = %u", al, [al retainCount]); 
    [al release]; 

    ARCLib *al2 = [ARCLib arcLib]; 
    NSLog(@"%p retainCount = %u", al2, [al2 retainCount]); 
} 

ARCLib없이 컴파일 - -

테스트 코드 ARC

를 컴파일
@implementation ARCLib 

+ (id)arcLib 
{ 
    return [[self alloc] init]; 
} 

- (id)init 
{ 
    self = [super init]; 
    if (self) 
    { 
     NSLog(@"%p init",self); 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    NSLog(@"%p dealloc",self); 
} 

@end 

결과

2012-12-13 20:15:21.879 ARCTest[15206:907] 0x1e821500 init 
2012-12-13 20:15:21.883 ARCTest[15206:907] 0x1e821500 retainCount = 1 
2012-12-13 20:15:21.884 ARCTest[15206:907] 0x1e821500 dealloc 
2012-12-13 20:15:21.885 ARCTest[15206:907] 0x1dd26060 init 
2012-12-13 20:15:21.886 ARCTest[15206:907] 0x1dd26060 retainCount = 1 
2012-12-13 20:15:21.893 ARCTest[15206:907] 0x1dd26060 dealloc 

질문에 대한 답변

obj1을 해제해야하지만, obj2를 해제 할 필요는 없습니다.

+0

'retainCount'가 autorelease 상태 나 언더 스레드 (내부 구현 세부 사항)의 활동을 반영하지 않기 때문에 실제로는 아무 것도 증명하지 않습니다. 우연의 결론은 정확합니다. – bbum

+0

@bbum 당신이 내 코드를 잘못 이해했습니다. retainCount는 아무것도 표시하지 않습니다. 데모 코드는 밑받침 autorelease 수영장이 우리를 위해 마법을 일으켰다는 것을 증명합니다. – howanghk

+0

그런 다음 왜 retainCount가 있습니까? 반환 된 값은이 컨텍스트에서는 유용하지 않습니다. – bbum