2009-09-06 3 views
5

많은 iPhone 코드 샘플 (Apple 등)은 다음과 같은 코드를 포함합니다.목표 C : ui 객체를 만든 직후에 왜 릴리즈해야 하는가?

- (void)viewDidLoad { 
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame]; 

// add the top-most parent view 
UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame]; 
contentView.backgroundColor = [UIColor blackColor]; 
self.view = contentView; 
[contentView release]; 

levelView = [[LevelView alloc] initWithFrame:applicationFrame viewController:self]; 
[self.view addSubview:levelView]; 

calibrationView = [[CalibrationView alloc] initWithFrame:applicationFrame viewController:self]; 
} 

이 스 니펫은 BubbleLevel 샘플 프로젝트에서 가져온 것입니다.

내 질문 : 왜 release 메시지가 contentView로 전송됩니까? self.view에서 contentView에 대한 참조가 유지되며이 메소드뿐만 아니라 앱의 수명 동안 분명히 사용하고 싶습니다. 호출 해제로 뷰가 해제되지 않습니까?

+0

설명해 주셔서 감사합니다. –

답변

6

retain/release을 단순히 균형을 잡는 것으로 생각하지 마십시오. 그들이하는 일은 소유권을 이전하는 것입니다. 소유권에 대한 아이디어를 이해하고 Cocoa의 메모리 관리를 이해합니다.

소유권이 범위로 설정됩니다. 메서드 범위, 개체 인스턴스 범위 또는 전역 응용 프로그램 범위입니다. 방법 은 보유 된 로컬 변수를 가지고을 소유합니다. 개체 인스턴스 은 보유 된 인스턴스 변수를 가지고을 소유합니다.그리고 응용 프로그램 은 보유 된 전역 변수를 가지고을 소유합니다.

현재의 방법을 사용하면 alloc라는 이름의 메소드 호출에서 그것을받은 경우 개체를 소유하거나 새로운 단어를 포함하거나 (newSprocket 또는 mutableCopy에서와 같이) 를 복사합니다. 다른 방법으로 부여 된 모든 객체는 소유하지 않습니다. 예를 들어 메소드에 대한 인수 또는 결과는 대부분의 메소드 호출입니다.

자신이 소유하지 않은 오브젝트 인스턴스에 액세스 할 수 있으며 항상 그렇게합니다. 객체 인스턴스가 현재 메소드 의 실행을 지나서 살기를 원하면 retain으로 소유권을 명시 적으로 가져 가면됩니다 (또는 니키 피티가되고 싶다면 run-loop).

이 코드 줄은 로컬 변수 contentView에서 참조 된 개체 인스턴스의 소유권을 가져옵니다. 메서드 loadView이 이제 개체를 소유합니다.

UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame]; 

다음으로 개체 인스턴스 자체는 속성이 보유 된 것으로 선언되므로 소유권을 갖습니다. 이제 개체 인스턴스에는 메서드와 클래스라는 두 가지 소유자가 있습니다.

self.view = contentView; 

여기서부터는이 메소드의 로컬 변수를 통해 뷰 객체에 액세스하지 않습니다. 이 방법은 더 이상 필요 없기 때문에 소유권을 종료합니다. 이제 객체는 객체 인스턴스에 의해서만 소유되며이 메소드의 경우 더 이상 문제이 아닙니다.

[contentView release]; 
+0

위대한 설명. 그러나 우선 인스턴스를 할당 했으므로 인스턴스를 릴리스해야한다고 강조하는 것이 좋습니다. 더 이상 필요 없다는 것뿐만 아니라 메서드가 끝나면 로컬 변수에 액세스 할 수 없게됩니다. –

8

아니요. 왜냐하면 self.view = contentView에 그대로 유지됩니다. 유지 보수와 해제 호출 간의 균형을 유지해야하므로 할당을 균형 잡기 위해 호출을 해제해야합니다.

5

다른 언어로 익숙하다면 self.view = contentView을보고 "아, 인스턴스 변수를 지정하고 있습니다."라고 생각하는 것이 자연 스럽습니다. 그러나 Objective-C의 객체는 항상 포인터이므로 인스턴스 변수에 점을 할당 할 수 없습니다. 그것은 속성 접근 자입니다. 대부분의 경우 정확하게는 [self setView:contentView]을 작성하는 것과 같습니다. 대부분의 경우

는, 그 setter 메소드는 다음과 같이 구현됩니다 : 당신이 속성을 설정할 때

- (void)setView:(UIView *)view { 
    if (view != _view) { 
     [_view release]; // where _view is the name of the actual instance variable 
     _view = [view retain]; 
    } 
} 

이 같은 경우는, 그것이 유지되고있다. 따라서 객체를 배포해야합니다. 그렇지 않으면 객체 할당으로 인해 발생하는 초기 소유권이 해제되지 않습니다.

13

Ölbaum은 self.view = contentView;이보기를 유지한다고 말하면 정확합니다. 즉, 할당이 취소되지 않습니다. 당신이 UIViewController에 대한 (또는 헤더) 문서를 보면

, 당신이 볼거야 view 속성은 다음과 같이 선언된다 :

@property(nonatomic, retain) UIView *view; 

이 그러나이 동작은 항상 사건되지 않습니다 뷰 속성이 설정 될 때마다 (foo.view = anotherView 또는 [foo setView:anotherView];) 다른 뷰가 유지된다는 것을 의미합니다. view 속성이 선언 된 것처럼 :

@property(nonatomic, assign) UIView *view; 

그런 다음보기는 이 유지되지 않습니다. 인스턴스 변수에 간단한 포인터 할당을 수행합니다. 이 경우 이후 release에서 contentView으로보기가 삭제된다는 것은 맞을 것입니다. 즉 컨트롤러에 부실 포인터가있는 것이므로 앱이 다운 될 가능성이 있습니다.

즉, 속성을 사용할 때 retain 또는 assign인지 확인하십시오. (말하지 않으면, 그것은 assign입니다.) 그런 다음 그에 따라 메모리 관리를 처리하십시오.