簡體   English   中英

iOS - 管理IBOutlets內存的最佳方法是什么?

[英]iOS - What is best way to manage memory for IBOutlets?

我一直在審查Apple文檔和示例代碼,以嘗試確定管理IBOutlet內存的最佳方法。 至少可以說,我有點困惑。

CurrentAddress示例代碼將IBOutlets聲明為屬性:

@interface MapViewController : UIViewController <MKMapViewDelegate, MKReverseGeocoderDelegate>

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

大。 這些是在dealloc中發布的:

- (void)dealloc
{
    [mapView release];
    [getAddressButton release];
    [super dealloc];
}

現在不應該將這些屬性設置為分配? 因為當設置為retain時,IBOutlet的保留計數將增加兩次:一次加載nib時和另一次設置屬性時? 將這些屬性設置為nil而不是在dealloc中釋放不是更好嗎?

Apple文檔說我們應該保留iOS的屬性。
留存網點應該被釋放和nil “編在這兩個deallocviewDidUnload

在Mac上,加載筆尖時,每個未由superview保留的插座會自動保留。 iOS的情況並非如此。 這就是為什么理論上只保留視圖層次結構中視圖以外的出口的原因。

Jeff LaMarche就這一主題發表了一篇非常有用的文章: Outlets,Cocoa vs. Cocoa Touch

一旦nib加載器完成加載所有內容並連接所有IBOutlet,它就會自動釋放它加載的所有對象。 如果您的IBOutlet屬性聲明為assign ,則下次自動釋放池清空時,它指向的對象將被刪除。

您可以在dealloc中將屬性設置為nil而不是直接釋放它們,結果是相同的。 需要注意的是,如果您提供了自己的setter實現,則需要記住,對象的某些其他成員可能已經被釋放。

這與MacOSX和iOS不同。 在iOS中,加載視圖並建立nib連接后,保留計數將為2。

這些元素中的每一個都將由視圖保留一次,並由控制器保留一次。 視圖中的其他元素僅由視圖保留。

當您的控制器釋放這兩個元素時,它們的保留計數會降至1。 之后調用[super dealloc]。 UIViewController在其dealloc中有一個[view release],因此視圖被釋放(除非保留在其他地方,或之前已發布)。 取消分配視圖時,它會釋放其子視圖,並最終完全釋放元素。

dealloc中首選[object release]的原因是鍵值編碼(或您自己的代碼)可能會導致在編寫[self setObject:nil]時運行其他代碼。 這可能會導致其他對象在解除分配自身時與控制器進行交互。 出於同樣的原因,不應在init方法中使用setter。

剛剛發布的第二個原因。 通過保留值而不將其設置為nil,我們將注意到代碼在dealloc期間是否錯誤地訪問了我們對象上的變量。 這可以幫助捕獲可能不容易追蹤的錯誤。

我假設你@synthesize這些屬性。 如果你沒有,你需要手動釋放自己。 你的假設非常正確,如果你在設置一個屬性時繼續保留,你就會泄漏內存。

讓我們想一想......在我們擁有花哨的@synthesize聲明之前,屬性曾經是什么樣子?

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
}

現在,你不需要輸入這些東西,因為@synthesize很酷並為你生成,如果你沒有指定nonatomic東西,它也會產生@synchronized塊,這也是非常好的。

如果您指定了assign而不是retain ,那么您將獲得類似的結果

id _propertyName; // the ivar

- (id) propertyName {
  return _propertyName;
}

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

當事物不是對象時,這是你唯一可以做的事情,因為它們只是值(有時也稱為值類型,對象是引用類型)。 由於無法保留值類型,因此其他類型的塊沒有任何意義。 繼續嘗試用BOOL創建一個retain屬性,看看LLVM或GCC告訴你去做什么;)

不應該將這些屬性設置為分配? 因為當設置為retain時,IBOutlet的保留計數將增加兩次:一次加載nib時和另一次設置屬性時

好吧,你發布的代碼是正確的。

當你使用:

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

你只是告訴xCode創建一個setter方法,它將創建你的MKMapView對象,並在你每次調用時保留它

yourMapViewController.mapView = someMapView; // from out

// or

self.mapView = someMapView; // from in

之后mapView保留計數增加+1並且你的MapViewController代碼需要'現在你可以指向mapView並管理它...

不要擔心IB nib文件...

當您使用nib加載UIViewController時,在您的情況下使用類MapViewController:UIViewController,當您釋放MapViewController時,IB nib對象將釋放...只關心您保留的對象...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM