IOS開發--循環引用問題,普通控件爲何用weak,代理爲何用weak,block內用到外面的東

全部的引用計數系統,都存在循環應用的問題。spa

例以下面的引用關係對象:代理

 a建立並引用到了對象b.指針

對象b建立並引用到了對象c.orm

對象c建立並引用到了對象b.對象

這時候b和c的引用計數分別是2和1。當a再也不使用b,調用release釋放對b的全部權,由於c還引用了b,因此b的引用計數爲1,b不會被釋放。b不釋放,c的引用計數就是1,c也不會被釋放。今後,b和c永遠留在內存中,形成內存浪費。這種狀況,必須打斷循環引用,經過其餘規則來維護引用關係。
生命週期

那麼普通控件爲何要用weak:內存

以下圖控制器中的View經過[self.view addSubview:btn];已經將Btn增長了強引用,因此不會被銷燬,因此若是想把btn當作屬性,沒有必要在property中使用強引用浪費資源。資源

若是要用強引用也能夠,由於在控制器銷燬以後,控制器view也銷燬了,因此btn銷燬,不會形成強引用。it

代理爲何要用weak以下圖:io

假設把代理設置成strong那麼就會執行語句UIScrollView*scrollView=[UIScrollView alloc]init];scrollView.delegate=self;(self表明控制器)後,

當控制器想要銷燬時,控制器被一個強指針指着,而scrollView添加到控制器view中也被強指針指着,也沒法銷燬,那麼它的delegate不會銷燬。delegate指向控制器。形成了循環引用。把delegate變成weak:當控制器生命週期結束時,view隨之銷燬,內部子空間也隨之銷燬,delegate也就銷燬了。


block內用到了外面的東西,須要轉換成weak指針,不然會形成循環引用 以下圖:

有這樣一段代碼,代碼本意沒必要理解:mail有一個block屬性,那麼block內有個郵件控制器須要設置代理。

ShareViewController內部強指針指向用Group,Group內部的items強指針指向mail對象,mail對象有個option屬性(block),option內部用到了self也就是控制器,因此block(option是copy類型的)會用一個強指針指向self。注意:這裏不和上邊同樣,不要被vc的代理(代理是weak的)所迷惑,是block強指針指向了self。形成了循環引用誰都沒辦法被銷燬。

解決辦法:使用:

__unsafe_unretained typeof(self) selfVc =self;

__unsafe_unretained HYShareViewController *selfVc =self;在block中讓他對self只能進行弱引用。

或者把__unsafe_unretain改爲__weak。(__unsafe_unretain和__weak的區別請見下一篇<OC語法--__unsafe_unretain、__strong、__weak、__autoreleasing這四種屬性的做用>


    HYSettingItem *mail = [HYSettingArrowItemitemWithIcon:@"MailShare"title:@"郵件分享"destVcClass:nil];

    mail.option = ^{

       //不能發郵件

        if (![MFMailComposeViewControllercanSendMail])return;

        MFMailComposeViewController *vc = [[MFMailComposeViewControlleralloc]init];

        [vcsetSubject:@"會議"];

        [vc setMessageBody:@"今天下午開會吧"isHTML:NO];

        vc.mailComposeDelegate = selfVc;

       //顯示控制器

        [selfVc presentViewController:vcanimated:YEScompletion:nil];

    };

 HYSettingGroup *group = [[HYSettingGroupalloc]init];

    group.items =@[sina, sms, mail];

    [self.dataaddObject:group];

}

相關文章
相關標籤/搜索