眾所周知臀叙,從IB中拖出來的outlet Xcode會默認設置為weak笆豁,那么代碼new出來并且addSubview到self.view的view郎汪,我們在property里要設置為strong還是weak呢。
Weak or Strong?
假設一個ViewController的self.view中有一個Label闯狱,那么他們三者的關系是:
可以看到Label的所有者其實是self.view煞赢,正常來說一個對象只有一個所有者,如果再將ViewController中的Label引用聲明為strong哄孤,那么當label從self.view中移除后照筑,label將不會銷毀,造成View的冗余。
于是我們愉快地把Label聲明為weak凝危,但是在初始化label的時候饭弓,Xcode又猝不及防地扔給我們一個warning。
咦媒抠,我們addSubview之后self.label不是已經(jīng)被self.view強引用了嘛,這又是什么鬼為什么Xcode還跟我們說都是weak惹的禍這個對象馬上就要被釋放了咏花。編譯一下試試趴生,發(fā)現(xiàn)ViewController里面果然一片雪白,完全沒有剛剛加進去的label的影子昏翰,看來Xcode沒有騙我們苍匆。
Label消失的原因
我們來逐步分析一下這幾句話背后引用計數(shù)的變化:
self.label = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
這句話其實應該拆成兩句話,首先alloc出了一個UILabel的臨時變量棚菊,然后再使用setLabel將臨時變量復制給self.label浸踩。其中引用計數(shù)變化如下
id temp = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];? ? ? //tempLabel引用計數(shù)為1
[self setLabel: temp];? ? ? ? ? //由于self.label是weak,因此此處引用計數(shù)還是1
然后接下來的代碼中沒有再用到temp,temp被釋放统求,此時引用計數(shù)為0检碗,temp被設為nil,于是self.label也被設為nil
[temp release];? ? ? ? //引用計數(shù)變?yōu)?
最后addSubview時只add了一個nil的view码邻,引用計數(shù)并不能增加折剃,所以我們在運行時才沒有看到new出來的label。
[self.view addSubview:self.label];? ? ? ? ? ? ? //此處等于[self.view addSubview:nil];
正確的打開方式
正確的打開方式是先用一個臨時變量把init出來的變量hold住像屋,防止temp在執(zhí)行的過程中被釋放怕犁,先亮代碼:
UILabel *tempLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
self.label = tempLabel;
self.label = @"Hello World";
[self.view addSubview:self.label];
這段話的引用計數(shù)過程是
UILabel *tempLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
這句話可以拆成兩句
id temp = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];? ? ? ? ? //temp引用計數(shù)為1
UILabel *tempLabel = temp;? ? ? ? ? //局部變量默認是strong,temp引用計數(shù)增至2
self.label = tempLabel;? ? ? ? //self.label是weak,不改變引用計數(shù)
self.label = @"Hello World";
[self.view addSubview:self.label];? ? ? ? ? //引用計數(shù)+1己莺,temp的引用計數(shù)為3
//這段代碼執(zhí)行完后奏甫,臨時變量將被釋放
[tempLabel release];? ? ? ? //temp引用計數(shù)為2
[temp release];? ? ? ? ? ? //temp引用計數(shù)為1
整段話執(zhí)行完后,既保證了temp在執(zhí)行過程中過早釋放凌受,又保證了在執(zhí)行完后temp的引用計數(shù)為1阵子,因此是初始化UIView的property較為科學的方法。
本文是從一個大牛的微博里拷貝過來的胁艰,主要是為了以后看方便款筑。他微博里有很多好文章
可以關注一下
原文鏈接?iOS 入門級攻城尸的微博