iOS 之Block (循環(huán)引用和基礎(chǔ)使用)

所謂block就是Objective-C的對象一個block本質(zhì)上就是一個函數(shù)指針,即那個代碼快的內(nèi)存地址。block常用作傳值,實際上就是把block的地址傳到要調(diào)用block的地方。閉包就是能夠讀取其它函數(shù)內(nèi)部變量的函數(shù).

Block 函數(shù)聲明方法

** 第一種方法 typedef + 屬性**

Xcode 輸入 ty 會有方法提示
typedef <#返回值類型#>(^<#Block名稱#>)(<#參數(shù)#>);

如定義一個 Block:無返回值,有參數(shù),參數(shù)類型為 NSSTring 類型
typedef void(^myBlock)(NSString *); 
@property (nonatomic, copy) MyBlock block;//屬性

** 第二種 直接屬性聲明 **

@property (nonatomic, copy)void (^myBlock)(NSString *);

Block 方法實現(xiàn),調(diào)用

    /** 方法 一 屬性聲明 Block*/
    self.myBlock2 = ^(NSString *str2){
        
        NSLog(@"%@" , str2);
    };
    
    //調(diào)用 Block
    self.myBlock2(@"我也愛你");
    NSLog(@"屬性直接聲明方法:%@", self.myBlock2);
    
    
    /** 方法 二 typedef + 屬性聲明*/
    myBlock newBlock = ^(NSString *str){
        
        // 輸出傳入值
        NSLog(@"%@",str);
    };
    
    //調(diào)用 Block
    newBlock(@"我愛你");
    NSLog(@"typedef 方法:%@", newBlock);



Block 為什么使用 Copy 修飾

Block屬性的聲明,首先需要用copy修飾符,因為只有copy后的Block才會在堆中,棧中的Block的生命周期是和棧綁定的.棧區(qū)的特點就是創(chuàng)建的對象隨時可能被銷毀,一旦被銷毀后續(xù)再次調(diào)用空對象就可能會造成程序崩潰,在對block進行copy后,block存放在堆區(qū).所以在使用Block屬性時使用Copy修飾.

因為block創(chuàng)建的時候,它的內(nèi)存是分配在棧上的(stack),所以如果出了這個作用域他就會被銷毀,所以如果在作用域外使用block的話就會崩潰,使用copy修飾block會把block拷貝到堆(heap)上,所以用copy修飾.*

Block 使用時的循環(huán)引用問題

有一個類A,在A類中有一個block屬性,在控制器中,我們創(chuàng)建A對象,并且把它賦值給一個A類型的屬性,再給A的block屬性賦值,如果這時候在block代碼塊中引用了self就會出現(xiàn)一下這種現(xiàn)象,
類A強引用block, 控制器強引用類A, block強引用控制器self, 造成循環(huán)引用.
那么如何解決循環(huán)引用呢,其實就是使一方變成弱引用就可以了,在這里把block對self的強引用變成弱引用。

通過人跟狗的關(guān)系,畫圖說明

局部變量銷毀,強指針互相引用
將一端變?yōu)槿踔羔?/div>

將狗變?yōu)槿踔羔樅?,由于不會造成計?shù)器 + 1, 局部變量銷毀,接著 Dog 對象會銷毀,然后Dog 中的 _per 實例變量會銷毀,然后Person對象銷毀,最后_dog實例變量銷毀,管理真科學(xué)!

ps:weak 和 assgin 區(qū)別

weak:weak弱指針,不會讓引用計數(shù)器+1,如果指向?qū)ο蟊讳N毀,指針會自動清空
assgin:unsafe_unretained修飾,不會讓引用計數(shù)器+1,如果指向?qū)ο蟊讳N毀,指針不會清空,如果在代碼里面有訪問到已經(jīng)釋放的對象會報壞內(nèi)存訪問,導(dǎo)致程序崩潰。

  • 在 MRC 模式下,為了防止循環(huán)引用, 我們使用__block來修飾在Block中使用的對象
__block typeof(self) weakSelf = self;

self.myBlock = ^(int paramInt){ 
//使用weakSelf訪問self成員
 [weakSelf anotherFunc];
};
  • 在 ARC 模式下,為了防止循環(huán)引用, 我們使用__weak 來修飾在Block中使用的對象
__weak typeof (self) weakSelf = self;;

self.myBlock = ^(int paramInt){ 
//使用weakSelf訪問self成員
 [weakSelf anotherFunc];
};

注意

如果要在ARC下, 為了防止循環(huán)引用, 使用__block來修飾在Block中使用的對象,仍然會被retain, 所以需要多做一些設(shè)置,需要將一端的指針置 nil

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容