2011-03-08 6 views
10

저는 Apple docs 및 샘플 코드를 검토하여 IBOutlets의 메모리를 관리하는 최선의 방법을 결정하려고했습니다. 나는 적어도 혼란 스럽다.iOS - IBOutlets의 메모리를 관리하는 가장 좋은 방법은 무엇입니까?

CurrentAddress 샘플 코드는 속성으로 IBOutlets를 선언

@interface MapViewController : UIViewController <MKMapViewDelegate, MKReverseGeocoderDelegate> 

{ 
    MKMapView *mapView; 
    UIBarButtonItem *getAddressButton; 
} 
@property (nonatomic, retain) IBOutlet MKMapView *mapView; 
@property (nonatomic, retain) IBOutlet UIBarButtonItem *getAddressButton; 

좋아요. 그리고 이들은 dealloc에서 해제됩니다 :

이제 이러한 속성을 할당해서는 안됩니까? 보유하도록 설정하면 IBOutlet의 보유 수는 두 번 증가합니다 : 펜촉이로드되고 속성이 설정 될 때 한 번? dealloc에서 해제하는 대신이 속성을 nil로 설정하는 것이 더 좋지 않습니까?

답변

7

Apple docs는 iOS의 속성을 유지해야한다고 말합니다.
보존 된 출구는 deallocviewDidUnload 모두에 nil '을 입력해야합니다.

Mac에서는 수퍼 뷰가 유지하지 않는 모든 콘센트가 펜촉을 넣을 때 자동으로 유지됩니다. iOS에서는 그렇지 않습니다. 이것이 이론적으로 뷰 계층 구조의 뷰가 아닌 다른 콘센트 만 유지하는 것이 이론적으로 타당한 이유입니다.

이 주제와 관련하여 Jeff LaMarche의 유용한 게시물이 있습니다 : Outlets, Cocoa vs. Cocoa Touch.

+0

@ Jilouc : dealloc 메소드에서,'IBOutlet'을 해제 한 직후에 왜 그것을 null로 설정하지 않았습니까? 이러한 호출을 두 가지 방법으로 분리하지 않으면 잠재적 인 문제가 발생할 수 있습니다. – FreeAsInBeer

+0

당신은 아마도 그것을 공개하지 않기 때문에 (아마도 @synthesize 내부에 릴리스 될 것입니다) viewDidUnload가 메모리를 더 빨리 해제하는 dealloc보다 빨리 발생합니다. – slf

+0

충분히 정확하지 않았기 때문에 (답변 편집). 내 콘센트를 dealloc에서도 사용하지 않았습니다. 일반적으로, 나는'dealloc'에서'viewDidUnload' (release + nil을 처리합니다)와'[myOutlet release], myOutlet = nil;'에서'self.myOutlet = nil'을 사용합니다. 그러나 그것은 단지 습관 일뿐입니다. – Jilouc

2

닙로드 장치가 모든로드를 완료하고 모든 IBOutlet을 연결하면로드 된 모든 오브젝트를 자동 렌더링합니다. IBOutlet 속성이 assign으로 선언 된 경우 다음에 자동 해제 풀이 비워진 다음에 가리키는 객체가 삭제됩니다.

dealloc에서 특성을 직접 해제하지 않고 nil로 설정할 수 있습니다. 결과는 동일합니다. 주의해야 할 점은 setter에 대한 구현을 직접 제공했다면 객체의 다른 멤버 중 일부가 이미 릴리스되었을 수 있음을 명심해야합니다.

1

MacOSX 및 iOS의 경우와 다릅니다. iOS에서는보기가로드되고 nib 연결이 설정된 후 보유 수는 2가됩니다.

이러한 각 요소는보기에 의해 한 번, 컨트롤러에 의해 한 번 유지됩니다. 뷰의 추가 요소는 뷰에서만 유지됩니다.

컨트롤러가 두 요소를 해제하면 보유 개수가 1로 줄어 듭니다. 그 후 [슈퍼 dealloc]이 호출됩니다. UIViewController는 dealloc에서 [view release]를 가지므로보기가 해제됩니다 (다른 곳에 보관되거나 이전에 릴리스되지 않은 경우). 뷰의 할당이 해제되면 하위 뷰가 해제되고 요소가 완전히 해제됩니다.

[object release]가 dealloc에서 선호되는 이유는 [self setObject : nil]을 쓸 때 키 - 값 코딩 (또는 사용자 코드)으로 인해 추가 코드가 실행될 수 있기 때문입니다. 이로 인해 다른 개체가 컨트롤러 할당을 취소하는 중일 때 잠재적으로 다른 개체가 컨트롤러와 상호 작용할 수 있습니다. setter는 동일한 이유로 init 메소드에서 사용되어서는 안됩니다.

방금 ​​출시하는 두 번째 이유가 있습니다. 값을 남겨두고 nil로 설정하지 않으면 코드가 dealloc 중에 객체의 해당 변수에 잘못 액세스하는 것을 알 수 있습니다. 이렇게하면 쉽게 추적 할 수없는 버그를 잡을 수 있습니다.

0

나는 이러한 속성이 이라고 가정합니다. 그렇지 않은 경우 수동으로 해제해야합니다. 속성이 설정되었을 때 계속 유지한다면 메모리가 누출 될 것이라는 가정에서 매우 정확합니다.

생각해 봅시다. ... 우리가 공상성명을하기 전에 어떤 속성을 사용 했습니까? @synthesize는 시원하고도 꽤되는, nonatomic 인 것으로 뭔가를 지정하지 않은 경우 당신을 위해, 또한 @synchronized 블록을 생성하는 것을 생성하기 때문에 지금

id _propertyName; // the ivar 

- (id) propertyName { 
    return _propertyName; 
} 

- (void) setPropertyName:(id)v { 
    if (_propertyName) { 
    [_propertyName release]; // release the previously retained property 
    } 
    _propertyName = [v retain]; // retain this one so it doesn't fly away on us 
} 

, 당신은이 물건을 입력 할 필요가 없습니다 rad. 대신 retainassign를 지정한 경우 그들은 또한 때때로 언급 된 유일한 값 (때문에

, 당신이 당신이 일이 물체하지 않을 때 할 수있는 유일한 방법에 관한이

id _propertyName; // the ivar 

- (id) propertyName { 
    return _propertyName; 
} 

- (void) setPropertyName:(id)v { 
    _propertyName = v; 
} 

뭔가를 얻을 것 값 유형으로 객체는 참조 유형입니다. 값 유형을 유지할 수 없으므로 다른 유형의 블록은 이해가되지 않습니다. 가서 BOOL와 유지 속성을 만들고 LLVM 또는 GCC가 무엇을 함께 할 가고 당신에게 무엇을 보려고)

0

이러한 속성은 지정 로 설정되어서는 안된다? , 을 유지하기 위해 설정할 때 함께 IBOutlet의 유지 카운트가되기 때문에 두 배 증가 : 펜촉이 속성이 설정되어 또 다른 시간이로드 이며, 한 번 할 때 잘

, 당신이 게시 된 코드가이 권리로이다 .

당신이 사용하는 경우 :

@property (nonatomic, retain) IBOutlet MKMapView *mapView; 

당신이 당신 MKMapView 객체를 생성하는 setter 메소드를 만들고 카운트 증가를 유지하는 것이지도보기 후

yourMapViewController.mapView = someMapView; // from out 

// or 

self.mapView = someMapView; // from in 

를 호출 할 때마다 그것을 유지하기 위해 엑스 코드를 말하고있다 +1 및 MapViewController 코드가 필요합니다. 이제 mapView를 가리켜 관리 할 수 ​​있습니다 ...

걱정하지 마세요. R IB에 펜촉 파일이 ...

당신이 당신의 경우, 펜촉으로 클래스 MapViewController을의 UIViewController를로드

가 : 당신이 당신의 MapViewController을 떼면의 UIViewController에서, IB 펜촉 개체를 발표 할 예정이다 ... 단지의 걱정 당신이 보유하고있는 객체 ...

관련 문제