讀古今文學網 > iOS編程基礎:Swift、Xcode和Cocoa入門指南 > 12.9 nib加載與內存管理 >

12.9 nib加載與內存管理

當nib加載時,它會實例化其nib對像(參見第7章)。這些實例化後的對象會發生什麼呢?視圖會保持其子視圖,但頂層對象呢,它們不是任何視圖的子視圖。答案就是它們不會增加保持計數;如果沒有其他對像保持它們,它們就會銷毀。

如果不希望這種情況發生(否則為何一開始要加載這個nib呢),那就需要捕獲到從nib中實例化的頂層對象的引用。可以通過兩種方式做到這一點。在通過調用NSBundle的loadNibNamed:owner:options:或UINib的instantiateWithOwner:options:加載nib時會返回一個NSArray,其中包含了nib加載機制所實例化的頂層對象。因此,保持這個NSArray或其中的對象即可。

在某些情況下,你可能根本就意識不到發生了這種情況。比如,當一個視圖控制器自動從故事板中實例化時,它實際上會從nib中加載,並且只有一個頂層對象,即視圖控制器本身。因此,該視圖控制器就是instantiateWithOwner:options:所返回的數組中的唯一一個元素。接下來,視圖控制器會被從該數組中提取出來,並由運行時保持,這是通過將其添加到視圖控制器層次體系中做到的。

另一種可能是通過插座變量來配置nib所有者,該插座變量會在nib頂層對像實例化時保持它們。第7章曾這麼做過,那時創建了一個如下所示的插座變量:


class ViewController: UIViewController {
    @IBOutlet var coolview : UIView!
  

接下來手工加載nib,並將該視圖控制器作為所有者:


NSBundle.mainBundle.loadNibNamed("View", owner: self, options: nil)
self.view.addSubview(self.coolview)
  

第一行從nib中實例化了頂層視圖,nib加載機制會將其賦給self.coolview。由於self.coolview是個強引用,它會保持視圖。這樣,第2行將視圖插入界面中時,它會還存在。

當視圖控制器加載包含了主視圖的nib時也會出現相同的情況。視圖控制器有一個view插座變量,並且是nib的所有者。這樣,視圖會由nib加載機制實例化並賦給視圖控制器的view屬性,該屬性會保持它。

不過,對於聲明的@IBOutlet屬性,你常常會將其標記為weak。這並不是必需的,省略weak標記也不會出現什麼問題。將這種插座變量標記為weak也可以正常使用,原因在於你知道該插座變量所指向的對象還會由其他對像保持,比如,它是視圖控制器主視圖的一個子視圖。視圖會由其父視圖保持,這樣除非後面將其從父視圖中移除,否則你知道它會一直存在,@IBOutlet屬性沒必要再保持它了。