果然還是對最基礎的知識了解不透徹,今天看一看iOS中的兩個修飾符:__block和__weak 。也是做一下溫習吧。
1、先說weak,<弱引用>
我們知道weak的使用,比如聲明一個控件屬性,就會用到weak。
看代碼:
@property(nonatomic,weak)UILabel *label;
當然這並不是說聲明控件就一定使用weak,相反的我在手動創建控件是大多數會使用strong。但如果你比較細心的話,你會發現我們使用xib時,使用的卻是weak這一屬性。那問題來了,我們使用strong 和 weak 的時機是何時呢?咱們接着往下看。
從storyboard 或者xib上創建控件
在控件放在view上的時候,已經形成了如下的引用關系,以UILabel為例:UIViewController->UIView->subView-> UILabel
然后你為這個UILabel聲明一個weak屬性
@property(nonatomic,weak) IBOOutlet UILabel * label;
相當於xib對這個label是強引用,你聲明的屬性對它是弱引用。
手動創建控件
a). 將控件聲明成strong
@property(nonatomic,strong) UIlabel * label;
那么你在實現這個控件時只需這樣:
_label = [[UIlabel alloc]init]; [self.view addSubview:_label]
b). 將控件聲明成weak
@property(nonatomic,weak) UIlabel * label;
那么你在實現這個控件時需要這樣:
UIlabel *label = [[UIlabel alloc]init]; _label = label; [self.view addSubview:_btn];
關於block循環引用的問題
由於block會復制外部的變量,所以如果不注意,就會造成循環引用。對於這種情況,需要將引用的一方變成weak,從而避免循環引用。
看代碼:
BlocksViewController *blockVC = [[BlocksViewController alloc]init]; __weak ViewController *weekSelf = self; /** * 1、使用弱引用來解決block循環引用問題 * * 2、block能截取自動變量,並且是不能在block塊中進行修改的(除非用 __block修飾符)這里的 weekSelf.textField.text 的值是被修改了,並且沒有使用 __block修飾符。原因是因為textField是全局變量,如果定義一個局部變量,比如:定義個 “text”是不能被修改的,編譯器會報錯, */
//block回調傳值
[blockVC returnValue:^(NSString *content) { weekSelf.textField.text = content; // text = content;//這里會提示錯失__block;
}];
2、strong和weak的區別
a) strong:強引用,也是我們通常說的引用,其存亡直接決定了所指向對象的存亡。如果不存在指向一個對象的引用,並且此對象不再顯示在列表中,則此對象會被從內存中釋放。
b) weak:弱引用,不決定對象的存亡。即使一個對象被持有無數個弱引用,只要沒有強引用指向它,那么還是會被清除。
c)strong和copy是用來修飾強引用的屬性,weak 用來修飾弱引用的屬性;
d)strong、weak 需要ARC支持才能使用,copy不需要ARC支持
e)strong與retain功能相似;weak與assign相似,只是當對象消失后weak會自動把指針變為nil;
3、關於__block
先看一段代碼:
@autoreleasepool { __block NSInteger value = 0; void (^block)(void) = ^{ value = 1; }; block(); NSLog(@"val = %ld", value); }
我們現在看着可能得不出什么結論,那么,我們再看下面的代碼,為了直觀,我以圖片的形式呈現:
現在對比就明顯了。
下面總結一下:
a) 1.__block對象在block中是可以被修改、重新賦值的。
b)2.__block對象在block中不會被block強引用一次,從而不會出現循環引用問題。
c)3.blocks可以訪問局部變量,但是不能修改。
如果修改局部變量,需要加__block ,所以__block 是讓修改外部變量的值.
對於 block 外的變量引用,block 默認是將其復制到其數據結構中來實現訪問的
對於用 __block 修飾的外部變量引用,block 是復制其引用地址來實現訪問的
4、__block 和__weak修飾符的區別:
1>.__block不管是ARC還是MRC模式下都可以使用,可以修飾對象,還可以修飾基本數據類型。
2>.__weak只能在ARC模式下使用,也只能修飾對象(NSString),不能修飾基本數據類型(int)。
3>.__block對象可以在block中被重新賦值,__weak不可以。
**鏈接:**
[談Objective-C block的實現]<http://blog.devtang.com/2013/07/28/a-look-inside-blocks/>
[Blocks are Objective-C`s]<http://rypress.com/tutorials/objective-c/blocks>
[iOS開發-由淺至深學習block]<http://www.cnblogs.com/luoxiaofu/p/5445327.html>