assign济瓢、weak、retain妹卿、strong旺矾、copy、__weak夺克、__strong箕宙、__block關(guān)鍵字

assign

用于對(duì)基本數(shù)據(jù)類型進(jìn)行賦值操作,不更改引用計(jì)數(shù)铺纽。也可以用來修飾對(duì)象柬帕,但是,被assign修飾的對(duì)象在釋放后狡门,指針的地址還是存在的雕崩,也就是說指針并沒有被置為nil,成為野指針融撞。如果后續(xù)在分配對(duì)象到堆上的某塊內(nèi)存時(shí)盼铁,正好分到這塊地址,程序就會(huì)crash尝偎。之所以可以修飾基本數(shù)據(jù)類型饶火,因?yàn)榛緮?shù)據(jù)類型一般分配在棧上,棧的內(nèi)存會(huì)由系統(tǒng)自動(dòng)處理致扯,不會(huì)造成野指針肤寝。

weak

修飾Object類型,修飾的對(duì)象在釋放后抖僵,指針地址會(huì)被置為nil鲤看,是一種弱引用。在ARC環(huán)境下耍群,為避免循環(huán)引用义桂,往往會(huì)把delegate屬性用weak修飾找筝;在MRC下使用assign修飾。weak和strong不同的是:當(dāng)一個(gè)對(duì)象不再有strong類型的指針指向它的時(shí)候慷吊,它就會(huì)被釋放袖裕,即使還有weak型指針指向它,那么這些weak型指針也將被清除溉瓶。

weak 與 assgin 的區(qū)別
assigin 可以用非 OC 對(duì)象,而 weak 必須用于 OC 對(duì)象

strong

ARC下的strong等同于MRC下的retain都會(huì)把對(duì)象引用計(jì)數(shù)加1急鳄。

copy

會(huì)在內(nèi)存里拷貝一份對(duì)象,兩個(gè)指針指向不同的內(nèi)存地址堰酿。一般用來修飾NSString等有對(duì)應(yīng)可變類型的對(duì)象疾宏,因?yàn)樗麄冇锌赡芎蛯?duì)應(yīng)的可變類型(NSMutableString)之間進(jìn)行賦值操作,為確保對(duì)象中的字符串不被修改 触创,應(yīng)該在設(shè)置屬性是拷貝一份坎藐。而若用strong修飾,如果對(duì)象在外部被修改了嗅榕,會(huì)影響到屬性。

strong與copy的區(qū)別

Copy吵聪,Strong的區(qū)別需要了解點(diǎn)內(nèi)存管理的知識(shí)凌那,Strong是ARC下引入的修飾,相當(dāng)于手動(dòng)管理內(nèi)存(MRC)下的retain吟逝,在相關(guān)代碼下帽蝶,常常看到有的人用copy修飾NSString,NSArray,NSDictionary等存在可變與不可變之分的對(duì)象块攒,常常會(huì)用copy励稳,而不是strong,下面代碼來解釋一下strong與copy的區(qū)別:

先說明一下什么叫做淺拷貝,什么叫做深拷貝;

淺Copy:可以理解為指針的復(fù)制囱井,只是多了一個(gè)指向這塊內(nèi)存的指針驹尼,共用一塊內(nèi)存。

深Copy:理解為內(nèi)存的復(fù)制庞呕,兩塊內(nèi)存是完全不同的新翎,也就是兩個(gè)對(duì)象指針分別指向不同的內(nèi)存,互不干涉住练。

舉例

首先在類延展中聲明兩個(gè)屬性變量

@property (nonatomic, strong)NSString * stringStrong;   //strong修飾的字符串對(duì)象  
@property (nonatomic, copy)NSString * stringCopy;       //copy修飾的字符串對(duì)象  

接著創(chuàng)建兩個(gè)不可變字符串(NSString)

//新創(chuàng)建兩個(gè)NSString對(duì)象  
NSString * strong1 = @"I am Strong!";  
NSString * copy1 = @"I am Copy!";  

將兩個(gè)屬性分別進(jìn)行賦值

//初始化兩個(gè)字符串  
self.stringStrong = strong1;  
self.stringCopy = copy1;  

分別打印一下四個(gè)變量的內(nèi)存地址:

NSLog(@"strong1 = %p",strong1);  
NSLog(@"stringStrong = %p",self.stringStrong);  
NSLog(@"copy1 = %p",copy1);  
NSLog(@"stringCopy = %p",self.stringCopy);  

結(jié)果如下:可以看出地啰,此時(shí)無論是strong修飾的字符串還是copy修飾的字符串,都進(jìn)行了淺Copy讲逛。

2018-03-11 18:59:06.332 StrongOrCopy[5046:421886] strong1 = 0x10a0b3078  
2018-03-11 18:59:06.332 StrongOrCopy[5046:421886] stringStrong = 0x10a0b3078  
2018-03-11 18:59:06.332 StrongOrCopy[5046:421886] copy1 = 0x10a0b3098  
2018-03-11 18:59:06.332 StrongOrCopy[5046:421886] stringCopy = 0x10a0b3098  

如果創(chuàng)建兩個(gè)可變字符串對(duì)象(NSMutableString)

//新創(chuàng)建兩個(gè)NSMutableString對(duì)象  
NSMutableString * mutableStrong = [NSMutableString stringWithString:@"StrongMutable"];  
NSMutableString * mutableCopy = [NSMutableString stringWithString:@"CopyMutable"]; 

分別對(duì)屬性再次進(jìn)行賦值

self.stringStrong = mutableStrong;  
self.stringCopy = mutableCopy;

分別打印一下四個(gè)變量的地址:結(jié)果如下:這時(shí)就發(fā)現(xiàn)了亏吝,用strong修飾的字符串依舊進(jìn)行了淺Copy,而由copy修飾的字符串進(jìn)行了深Copy,所以mutableStrong與stringStrong指向了同一塊內(nèi)存盏混,而mutableCopy和stringCopy指向的是完全兩塊不同的內(nèi)存蔚鸥。

2018-03-11 18:59:06.332 StrongOrCopy[5046:421886] mutableStrong = 0x7fccba425d60  
2018-03-11 18:59:06.332 StrongOrCopy[5046:421886] stringStrong = 0x7fccba425d60  
2018-03-11 18:59:06.332 StrongOrCopy[5046:421886] mutableCopy = 0x7fccba40d7c0  
2018-03-11 18:59:06.333 StrongOrCopy[5046:421886] stringCopy = 0x7fccba4149e0  

那么有什么用呢惜论,實(shí)例來看一下有什么區(qū)別:

首先是對(duì)不可變字符串進(jìn)行操作:

//新創(chuàng)建兩個(gè)NSString對(duì)象  
NSString * strong1 = @"I am Strong!";  
NSString * copy1 = @"I am Copy!";  
  
//初始化兩個(gè)字符串  
self.stringStrong = strong1;  
self.stringCopy = copy1;  
  
//兩個(gè)NSString進(jìn)行操作  
[strong1 stringByAppendingString:@"11111"];  
[copy1 stringByAppendingString:@"22222"];  

分別對(duì)在字符串后面進(jìn)行拼接,當(dāng)然這個(gè)拼接對(duì)原字符串沒有任何的影響株茶,因?yàn)椴豢勺冏宰址{(diào)用的方法都是有返回值的来涨,原來的值是不會(huì)發(fā)生變化的。打印如下启盛,對(duì)結(jié)果沒有任何的影響:

2018-03-11 19:15:26.729 StrongOrCopy[5146:439360] strong1 = I am Strong!  
2018-03-11 19:15:26.729 StrongOrCopy[5146:439360] stringStrong = I am Strong!  
2018-03-11 19:15:26.729 StrongOrCopy[5146:439360] copy1 = I am Copy!  
2018-03-11 19:15:26.729 StrongOrCopy[5146:439360] stringCopy = I am Copy!  

然后是對(duì)可變字符串進(jìn)行操作:

//新創(chuàng)建兩個(gè)NSMutableString對(duì)象  
NSMutableString * mutableStrong = [NSMutableString stringWithString:@"StrongMutable"];  
NSMutableString * mutableCopy = [NSMutableString stringWithString:@"CopyMutable"];  
  
//初始化兩個(gè)字符串  
self.stringStrong = mutableStrong;  
self.stringCopy = mutableCopy;  
  
//兩個(gè)MutableString進(jìn)行操作  
[mutableStrong appendString:@"Strong!"];  
[mutableCopy appendString:@"Copy!"];  

再來看一下結(jié)果:對(duì)mutableStrong進(jìn)行的操作蹦掐,由于用strong修飾的stringStrong沒有進(jìn)行深Copy,導(dǎo)致共用了一塊內(nèi)存僵闯,當(dāng)mutableStrong對(duì)內(nèi)存進(jìn)行了操作的時(shí)候卧抗,實(shí)際上對(duì)stringStrong也進(jìn)行了操作; 相反,用copy修飾的stringCopy進(jìn)行了深Copy鳖粟,也就是說stringCopy與mutableCopy用了兩塊完全不同的內(nèi)存社裆,所以不管mutableCopy進(jìn)行了怎么樣的變化,原來的stringCopy都不會(huì)發(fā)生變化向图。這就在日常中避免了出現(xiàn)一些不可預(yù)計(jì)的錯(cuò)誤泳秀。

2018-03-11 19:20:27.652 StrongOrCopy[5245:446189] stringStrong = StrongMutableStrong!  
2018-03-11 19:20:27.652 StrongOrCopy[5245:446189] mutableStrong = StrongMutableStrong!  
2018-03-11 19:20:27.652 StrongOrCopy[5245:446189] stringCopy = CopyMutable  
2018-03-11 19:20:27.652 StrongOrCopy[5245:446189] mutableCopy = CopyMutableCopy!  
總結(jié)

在不可變對(duì)象之間進(jìn)行轉(zhuǎn)換,strong與copy作用是一樣的榄攀,但如果在不可變與可變之間進(jìn)行操作嗜傅,strong與copy就不同了。

__weak

作為程序猿還是代碼具有說服力檩赢,上栗子:

首先定義一個(gè)類 MyObject 繼承 NSObject吕嘀,并添加一個(gè)屬性 text,重寫了description方法贞瞒,返回 text 的值偶房。這個(gè)主要是因?yàn)榫幾g器本身對(duì) NSString 是有優(yōu)化的,創(chuàng)建的 string 對(duì)象有可能是靜態(tài)存儲(chǔ)區(qū)永不釋放的军浆,為了避免使用 NSString 引起一些問題棕洋,還是創(chuàng)建一個(gè) NSObject 對(duì)象比較合適。

自定義了一個(gè) ZXLog 方法輸出對(duì)象相關(guān)值乒融,定義如下:

#define ZXLog(prefix,Obj) {NSLog(@"變量?jī)?nèi)存地址:%p, 變量值:%p, 指向?qū)ο笾担?@, --> %@",&Obj,Obj,Obj,prefix);}

代碼:

MyObject *obj = [[MyObject alloc]init];
obj.text = @"my-object";
ZXLog(@"obj", obj);
   
__weak MyObject *weakObj = obj;
ZXLog(@"weakObj", weakObj);
   
void(^testBlock)(void) = ^(){
    ZXLog(@"weakObj - block", weakObj);
};
testBlock();
obj = nil;
testBlock();

打印結(jié)果:

變量?jī)?nèi)存地址:0x7fff510b7c78, 變量值:0x60000001a270, 指向?qū)ο笾担?lt;MyObject: 0x60000001a270>, --> obj
變量?jī)?nèi)存地址:0x7fff510b7c70, 變量值:0x60000001a270, 指向?qū)ο笾担?lt;MyObject: 0x60000001a270>, --> weakObj
變量?jī)?nèi)存地址:0x60400044cfe0, 變量值:0x60000001a270, 指向?qū)ο笾担?lt;MyObject: 0x60000001a270>, --> weakObj - block
變量?jī)?nèi)存地址:0x60400044cfe0, 變量值:0x0, 指向?qū)ο笾担?null), --> weakObj - block

從上面的結(jié)果可以看到

  • block 內(nèi)的 weakObj 和外部的 weakObj 并不是同一個(gè)變量

  • block 捕獲了 weakObj 同時(shí)也是對(duì) obj 進(jìn)行了弱引用拍冠,當(dāng)我在 block 外把 obj 釋放了之后,block 內(nèi)也讀不到這個(gè)變量了

  • 當(dāng) obj 賦值 nil 時(shí)簇抵,block 內(nèi)部的 weakObj 也為 nil 了庆杜,也就是說 obj 實(shí)際上是被釋放了,可見 __weak 是可以避免循環(huán)引用問題的

接下來看第二段代碼:

MyObject *obj = [[MyObject alloc]init];
obj.text = @"my-object";
ZXLog(@"obj", obj);
    
__weak MyObject *weakObj = obj;
ZXLog(@"weakObj-0", weakObj);
    
void(^testBlock)(void) = ^(){
   __strong MyObject *strongObj = weakObj;
   ZXLog(@"weakObj - block", weakObj);
   ZXLog(@"strongObj - block", strongObj);
};
    
ZXLog(@"weakObj-1", weakObj);
testBlock();
ZXLog(@"weakObj-2", weakObj);
obj = nil;
testBlock();
ZXLog(@"weakObj-3", weakObj);

打印結(jié)果:

變量?jī)?nèi)存地址:0x7fff517bcc78, 變量值:0x60400000a420, 指向?qū)ο笾担?lt;MyObject: 0x60400000a420>, --> obj
變量?jī)?nèi)存地址:0x7fff517bcc70, 變量值:0x60400000a420, 指向?qū)ο笾担?lt;MyObject: 0x60400000a420>, --> weakObj-0
變量?jī)?nèi)存地址:0x7fff517bcc70, 變量值:0x60400000a420, 指向?qū)ο笾担?lt;MyObject: 0x60400000a420>, --> weakObj-1
變量?jī)?nèi)存地址:0x600000259df0, 變量值:0x60400000a420, 指向?qū)ο笾担?lt;MyObject: 0x60400000a420>, --> weakObj - block
變量?jī)?nèi)存地址:0x7fff517bcb28, 變量值:0x60400000a420, 指向?qū)ο笾担?lt;MyObject: 0x60400000a420>, --> strongObj - block
變量?jī)?nèi)存地址:0x7fff517bcc70, 變量值:0x60400000a420, 指向?qū)ο笾担?lt;MyObject: 0x60400000a420>, --> weakObj-2
變量?jī)?nèi)存地址:0x600000259df0, 變量值:0x0, 指向?qū)ο笾担?null), --> weakObj - block
變量?jī)?nèi)存地址:0x7fff517bcb28, 變量值:0x0, 指向?qū)ο笾担?null), --> strongObj - block
變量?jī)?nèi)存地址:0x7fff517bcc70, 變量值:0x0, 指向?qū)ο笾担?null), --> weakObj-3

如果你看過 AFNetworking 的源碼碟摆,會(huì)發(fā)現(xiàn) AFN 中作者會(huì)把變量在 block 外面先用 __weak 聲明晃财,在 block 內(nèi)把前面 weak 聲明的變量賦值給 __strong 修飾的變量這種寫法。

從上面例子我們看到即使在 block 內(nèi)部用 strong 強(qiáng)引用了外面的 weakObj ,但是一旦 obj 釋放了之后断盛,內(nèi)部的 strongObj 同樣會(huì)變成 nil罗洗,那么這種寫法又有什么意義呢?

下面再看一段代碼:

MyObject *obj = [[MyObject alloc]init];
obj.text = @"my-object";
ZXLog(@"obj", obj);

__weak MyObject *weakObj = obj;
ZXLog(@"weakObj-0", weakObj);

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    __strong MyObject *strongObj = weakObj;
    ZXLog(@"weakObj - block", weakObj);
    ZXLog(@"strongObj - block", strongObj);
    
    sleep(3);
    
    ZXLog(@"weakObj - block", weakObj);
    ZXLog(@"strongObj - block", strongObj);
});
NSLog(@"------ sleep 1s");
sleep(1);
obj = nil;
ZXLog(@"weakObj-1", weakObj);
NSLog(@"------ sleep 5s");
sleep(5);
ZXLog(@"weakObj-2", weakObj);

打印結(jié)果:

變量?jī)?nèi)存地址:0x7fff5f891c78, 變量值:0x6000000133f0, 指向?qū)ο笾担?lt;MyObject: 0x6000000133f0>, --> obj
變量?jī)?nèi)存地址:0x7fff5f891c70, 變量值:0x6000000133f0, 指向?qū)ο笾担?lt;MyObject: 0x6000000133f0>, --> weakObj-0
------ sleep 1s
變量?jī)?nèi)存地址:0x60000025a2a0, 變量值:0x6000000133f0, 指向?qū)ο笾担?lt;MyObject: 0x6000000133f0>, --> weakObj - block
變量?jī)?nèi)存地址:0x700000722d78, 變量值:0x6000000133f0, 指向?qū)ο笾担?lt;MyObject: 0x6000000133f0>, --> strongObj - block
變量?jī)?nèi)存地址:0x7fff5f891c70, 變量值:0x6000000133f0, 指向?qū)ο笾担?lt;MyObject: 0x6000000133f0>, --> weakObj-1
------ sleep 5s
變量?jī)?nèi)存地址:0x60000025a2a0, 變量值:0x6000000133f0, 指向?qū)ο笾担?lt;MyObject: 0x6000000133f0>, --> weakObj - block
變量?jī)?nèi)存地址:0x700000722d78, 變量值:0x6000000133f0, 指向?qū)ο笾担?lt;MyObject: 0x6000000133f0>, --> strongObj - block
變量?jī)?nèi)存地址:0x7fff5f891c70, 變量值:0x0, 指向?qū)ο笾担?null), --> weakObj-2

代碼中使用 sleep 來保證代碼執(zhí)行的先后順序钢猛。

從結(jié)果中我們可以看到伙菜,只要 block 部分執(zhí)行了,即使我們中途釋放了 obj命迈,block 內(nèi)部依然會(huì)繼續(xù)強(qiáng)引用它贩绕。對(duì)比上面代碼,也就是說 block 內(nèi)部的 __strong 會(huì)在執(zhí)行期間進(jìn)行強(qiáng)引用操作壶愤,保證在 block 內(nèi)部 strongObj 始終是可用的淑倾。這種寫法非常巧妙,既避免了循環(huán)引用的問題征椒,又可以在 block 內(nèi)部持有該變量娇哆。

綜合兩部分代碼,我們平時(shí)在使用時(shí)勃救,常常先判斷 strongObj 是否為空碍讨,然后再執(zhí)行后續(xù)代碼,如下方式:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    __strong MyObject *strongObj = weakObj;
    if(strongObj){
        // do something ...
    }
});

這種方式先判斷 Obj 是否被釋放蒙秒,如果未釋放在執(zhí)行我們的代碼的時(shí)候保證其可用性勃黍。

__block

直接上代碼:

MyObject *obj = [[MyObject alloc]init];
obj.text = @"my-object-1";
ZXLog(@"obj",obj);

__block MyObject *blockObj = obj;
obj = nil;
ZXLog(@"blockObj -1",blockObj);

void(^testBlock)(void) = ^(){
    ZXLog(@"blockObj - block",blockObj);
    MyObject *obj2 = [[MyObject alloc]init];
    obj2.text = @"my-object-2";
    ZXLog(@"obj2",obj2);
    blockObj = obj2;
    ZXLog(@"blockObj - block",blockObj);
};
ZXLog(@"%@",testBlock);
ZXLog(@"blockObj -2",blockObj);
testBlock();
ZXLog(@"blockObj -3",blockObj);

打印結(jié)果:

變量?jī)?nèi)存地址:0x7fff5ddc1c78, 變量值:0x60000000ac60, 指向?qū)ο笾担?lt;MyObject: 0x60000000ac60>, --> obj
變量?jī)?nèi)存地址:0x7fff5ddc1c70, 變量值:0x60000000ac60, 指向?qū)ο笾担?lt;MyObject: 0x60000000ac60>, --> blockObj -1
變量?jī)?nèi)存地址:0x7fff5ddc1c30, 變量值:0x60400045ce00, 指向?qū)ο笾担?lt;__NSMallocBlock__: 0x60400045ce00>, --> %@
變量?jī)?nèi)存地址:0x6040004588f8, 變量值:0x60000000ac60, 指向?qū)ο笾担?lt;MyObject: 0x60000000ac60>, --> blockObj -2
變量?jī)?nèi)存地址:0x6040004588f8, 變量值:0x60000000ac60, 指向?qū)ο笾担?lt;MyObject: 0x60000000ac60>, --> blockObj - block
變量?jī)?nèi)存地址:0x7fff5ddc1ba8, 變量值:0x60000000ace0, 指向?qū)ο笾担?lt;MyObject: 0x60000000ace0>, --> obj2
變量?jī)?nèi)存地址:0x6040004588f8, 變量值:0x60000000ace0, 指向?qū)ο笾担?lt;MyObject: 0x60000000ace0>, --> blockObj - block
變量?jī)?nèi)存地址:0x6040004588f8, 變量值:0x60000000ace0, 指向?qū)ο笾担?lt;MyObject: 0x60000000ace0>, --> blockObj -3

可以看到在 block 聲明前后 blockObj 的內(nèi)存地址是有所變化的,這涉及到 block 對(duì)外部變量的內(nèi)存管理問題税肪。

下面來看看 __block 能不能避免循環(huán)引用的問題:

MyObject *obj = [[MyObject alloc]init];
obj.text = @"11111111111111";
ZXLog(@"obj",obj);

__block MyObject *blockObj = obj;
obj = nil;
void(^testBlock)(void) = ^(){
    ZXLog(@"blockObj - block",blockObj);
};
obj = nil;
testBlock();
ZXLog(@"blockObj",blockObj);

打印結(jié)果:

變量?jī)?nèi)存地址:0x7fff57e48c78, 變量值:0x60000001b520, 指向?qū)ο笾担?lt;MyObject: 0x60000001b520>, --> obj
變量?jī)?nèi)存地址:0x604000457818, 變量值:0x60000001b520, 指向?qū)ο笾担?lt;MyObject: 0x60000001b520>, --> blockObj - block
變量?jī)?nèi)存地址:0x604000457818, 變量值:0x60000001b520, 指向?qū)ο笾担?lt;MyObject: 0x60000001b520>, --> blockObj

當(dāng)外部 obj 指向 nil 的時(shí)候溉躲,obj 理應(yīng)被釋放榜田,但實(shí)際上 blockObj 依然強(qiáng)引用著 obj益兄,obj 其實(shí)并沒有被真正釋放。因此使用 __block 并不能避免循環(huán)引用的問題箭券。

但是我們可以通過手動(dòng)釋放 blockObj 的方式來釋放 obj净捅,這就需要我們?cè)?block 內(nèi)部將要退出的時(shí)候手動(dòng)釋放掉 blockObj ,如下這種形式:

MyObject *obj = [[MyObject alloc]init];
obj.text = @"11111111111111";
ZXLog(@"obj",obj);

__block MyObject *blockObj = obj;
obj = nil;
void(^testBlock)(void) = ^(){
    ZXLog(@"blockObj - block",blockObj);
    blockObj = nil;
};
obj = nil;
testBlock();
ZXLog(@"blockObj",blockObj);

必須記住在 block 底部釋放掉 block 變量辩块,這其實(shí)跟 MRC 的形式有些類似了蛔六,不太適合 ARC這種形式既能保證在 block 內(nèi)部能夠訪問到 obj,又可以避免循環(huán)引用的問題废亭,但是這種方法也不是完美的国章,其存在下面幾個(gè)問題

當(dāng)在 block 外部修改了 blockObj 時(shí),block 內(nèi)部的值也會(huì)改變豆村,反之在 block 內(nèi)部修改 blockObj 在外部再使用時(shí)值也會(huì)改變液兽。這就需要在寫代碼時(shí)注意這個(gè)特性可能會(huì)帶來的一些隱患
__block 其實(shí)提升了變量的作用域,在 block 內(nèi)外訪問的都是同一個(gè) blockObj 可能會(huì)造成一些隱患掌动。

總結(jié)

__weak 本身是可以避免循環(huán)引用的問題的四啰,但是其會(huì)導(dǎo)致外部對(duì)象釋放了之后宁玫,block 內(nèi)部也訪問不到這個(gè)對(duì)象的問題,我們可以通過在 block 內(nèi)部聲明一個(gè) __strong 的變量來指向 weakObj柑晒,使外部對(duì)象既能在 block 內(nèi)部保持住欧瘪,又能避免循環(huán)引用的問題。

__block 本身無法避免循環(huán)引用的問題匙赞,但是我們可以通過在 block 內(nèi)部手動(dòng)把 blockObj 賦值為 nil 的方式來避免循環(huán)引用的問題佛掖。另外一點(diǎn)就是 __block 修飾的變量在 block 內(nèi)外都是唯一的,要注意這個(gè)特性可能帶來的隱患罚屋。

但是__block有一點(diǎn):這只是限制在ARC環(huán)境下苦囱。在非arc下,__block是可以避免引用循環(huán)的脾猛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末撕彤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子猛拴,更是在濱河造成了極大的恐慌羹铅,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愉昆,死亡現(xiàn)場(chǎng)離奇詭異职员,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)跛溉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門焊切,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人芳室,你說我怎么就攤上這事专肪。” “怎么了堪侯?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵嚎尤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我伍宦,道長(zhǎng)芽死,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任次洼,我火速辦了婚禮关贵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘卖毁。我一直安慰自己揖曾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著翩肌,像睡著了一般模暗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上念祭,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天兑宇,我揣著相機(jī)與錄音,去河邊找鬼粱坤。 笑死隶糕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的站玄。 我是一名探鬼主播枚驻,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼株旷!你這毒婦竟也來了再登?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤晾剖,失蹤者是張志新(化名)和其女友劉穎锉矢,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體齿尽,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沽损,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了循头。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绵估。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖卡骂,靈堂內(nèi)的尸體忽然破棺而出国裳,到底是詐尸還是另有隱情,我是刑警寧澤偿警,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布躏救,位于F島的核電站唯笙,受9級(jí)特大地震影響螟蒸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜崩掘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一七嫌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧苞慢,春花似錦诵原、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔓纠。三九已至,卻和暖如春吗蚌,著一層夾襖步出監(jiān)牢的瞬間腿倚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來泰國打工蚯妇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留敷燎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓箩言,卻偏偏與公主長(zhǎng)得像硬贯,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子陨收,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容