iOS開發——Block引起循環參考的解決方案

來源:互聯網
上載者:User

iOS開發——Block引起循環參考的解決方案

記憶體問題始終是軟體開發中的頭等大事,iOS開發中也不例外,在面試中也是必問的問題。今天我們主要來講講Block中涉及的循環參考問題。當我們自己一開始寫代碼的時候,可能會大量在block中使用self,但是當看到別人優秀的代碼的時候,發現別人常常不是用self,而使用weakSelf. 為什麼呢?

首先我先來說說記憶體管理的原則:

1.預設使用strong,可選weak。strong下不管成員變數還是屬性,每次使用指標指向一個對象,就會自動調用retain,並對舊對象調用release,在需要釋放的時候設為nil。

2.避免循環參考,否則手動設定nil釋放。

3.建立block匿名函數之前一般需要對self進行weak化,否則造成循環參考無法釋放controller。

首先Xcode為我們提供了良好的編譯環境,如果代碼中有可能出現循環參考的地方,Xcode會給我們警告:“Capturing 'self' strongly in this block is likely to lead to a retain cycle”.

block中的循環參考是這樣的:某個對象有一個copy或者strong成員變數或者屬性,這時block內部直接引用了成員變數或者self,這樣就產生了self持有block成員,block成員持有self,就會導致循環參考。因為self本身就是一個strong類型的變數。蘋果官方的建議是:傳進block之前,把self轉換成weak automatic的變數,這樣在block中就不會出現對self的強引用。如果在block執行完成之前,self被釋放,weakSelf也會置為nil。weak類型相對比較安全,因為可以在釋放後自動置為nil,不會引起野指標。那麼如何來聲明呢?

1.

__weak typeof(self) weakSelf = self;

這句話的意思是聲明了一個self類型的weak指標,名字叫做weakSelf. typeof是用來求參數類型的,這裡也就是來求self的類型。這樣定義出的weakSelf就是和self是一個類型,並且是原self的一個弱引用。

2.

__weak typeof(&*self) weakSelf = self;

3.

__weak MyViewController *weakSelf = self;

下面我通過代碼示範一下:

(1)聲明幾個block和一個屬性:

@interface ViewController (){    void(^myBlock1)(void);//該block參數為void,傳回值為void    void(^myBlock2)(void);    void(^myBlock3)(void);}@property (nonatomic,copy) NSString *person;@end

(2)使用weakSelf不會引起循環參考:
    __weak typeof(self) weakSelf = self;    NSLog(@"init--> value:%@,address=%p,self=%p",self.person,self.person,self);    myBlock1 = ^(void){        //這樣不會造成循環參考        NSLog(@"execute1--> value:%@,address=%p,weakSelf=%p",weakSelf.person,weakSelf.person,weakSelf);    };

(3)直接使用self,會循環參考:Xcode會給警告

    myBlock2 = ^(void){        //這樣造成循環參考        NSLog(@"execute2--> value:%@,address=%p,self=%p",self.person,self.person,self);    };

(4)要執行的方法抽取出來,也不會循環參考:

    myBlock3 = ^(void){        //這樣也不會造成循環參考,已經抽取出要執行的方法        [weakSelf myBlock3Func];    };
- (void)myBlock3Func{    NSLog(@"execute3--> value:%@,address=%p,self=%p",self.person,self.person,self);}
(5)block不是self的屬性或者變數時,在block內使用self也不會循環參考:
    //block不是self的屬性時,block內部使用self也不是循環參考    Animal *animal = [[Animal alloc] init];    animal.animalBlock = ^(void){        NSLog(@"animal--> value:%@,address=%p,self=%p",self.person,self.person,self);    };

(6)block的調用如下:

    myBlock1();    myBlock2();    myBlock3();    animal.animalBlock();    

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.