delegate 為什么用weak而不是strong或者assign?

始終覺得,好記性不如爛筆頭,寫博客還是非常有必要的,不但可以記錄自己學(xué)習(xí)到的知識,也還可以和別人一起分享。最重要的就是,整理博客的過程,也是再次學(xué)習(xí)的一個過程。。。

最近項(xiàng)目完成差不多了,得以空閑,打算重新開始博客之路,并要堅(jiān)持下去。好吧,不扯淡了,開始我的第一篇博客。

平常寫代碼,代理再常見不過了,寫了n次delegate,可是為啥用weak,總是一知半解,今天項(xiàng)目中再次用的代理,寫weak的時候,我仔細(xì)研究了一下,打算記錄下來,和大家一起分享。

1.為什么要用weak而不是用strong呢,因?yàn)閣eak是弱引用,weak屬性的變量是不為其所屬對象持有的,并且在該變量被銷毀之后,此weak變量的值會自動被賦值為nil,而strong會持有著這個屬性,不會被銷毀。

文字描述可能不是那么好理解,好了,上代碼:

舉個??

我創(chuàng)建了兩個類,一個是學(xué)生類student,一個是教師類teacher,給教師類添加個delegate的屬性,并且讓學(xué)生作為教師的代理。如代碼:

#import <UIKit/UIKit.h>

@class Teacher;

@protocol TeacherDelegate <NSObject>

@end

@interface Teacher : UIViewController

@property (nonatomic, weak) id <TeacherDelegate>delegate;

@end
#import "Teacher.h"

@interface Teacher ()

@end

@implementation Teacher

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)dealloc {
    NSLog(@"Teacher----delloc");
}

@end
#import "Student.h"
#import "Teacher.h"

@interface Student ()<TeacherDelegate>

@property (nonatomic, strong) Teacher *teacher;
@end

@implementation Student

- (instancetype)init {
    if (self = [super init]) {
        self.teacher = [[Teacher alloc] init];
        self.teacher.delegate = self;
    }
    return self;
}

- (void)dealloc {
    NSLog(@"student --- delloc");
}

@end
#import "ViewController.h"
#import "Student.h"
#import "Teacher.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    Student *student = [[Student alloc] init];
}
@end

由于ARC的原理可知,控制器中這個studetn對象,使用完后,就會被release了。在weak的修飾下,運(yùn)行結(jié)果為:

2017-09-27 17:52:17.151 代理demo[43047:3373078] student --- delloc
2017-09-27 17:52:17.151 代理demo[43047:3373078] Teacher----delloc

然后將weak換為strong后,無任何打印,說明沒有將對象釋放,該釋放的時候沒有釋放,這就是我們平時所說的內(nèi)存泄漏。
之所以會出現(xiàn)這個問題,就是因?yàn)閟trong的強(qiáng)引用,再直觀點(diǎn)的圖為下:

image.png
image.png

2.講解完strong和weak的區(qū)別了,但是有的會問,那assign也不會強(qiáng)持有該屬性啊,是否也可以使用assign?
先來說一下assign:assign屬性一般是對C基本數(shù)據(jù)類型成員變量的聲明,當(dāng)然也可以用在對象類型成員變量上,只是其代表的意義只是單純地拷貝所賦值變量的值。即如果對某assign成員變量B賦值某對象A的指針,則此B只是簡單地保存此指針的值,且并不持有對象A,也就意味著如果A被銷毀,則B就指向了一個已經(jīng)被銷毀的對象,如果再對其發(fā)送消息會引發(fā)崩潰。
大多數(shù)情況下,修飾delegate,既可以用weak,又可以用assign。因?yàn)樵趲缀跛袌鼍跋拢琩elegate所指向的對象C的生存期都是覆蓋了delegate成員變量本身所在的對象D的生存期的,所以,在D的生存期內(nèi),C所使用的D的指針都是有效的,所以這個時候使用assign是沒有關(guān)系的。
但是,用weak是更加安全些的,為什么這么說呢?舉個??:
用上圖的代碼來說,viewController擁有一個student對象以供業(yè)務(wù)的使用,student與viewController是一對一的關(guān)系,如果viewController被銷毀,則其對應(yīng)的student也就沒有存在的意義了,且viewController的銷毀也會馬上引發(fā)student的銷毀。所以student的delegate成員變量內(nèi)存管理屬性聲明為assign是沒有問題的,但是如果delegate是assign屬性,在viewController銷毀的時候,student因?yàn)槿匀槐黄渌胤揭枚鴮?dǎo)致其此時并沒有跟隨viewController一起銷毀,那么此時delegate指向了一個已經(jīng)被銷毀的對象(我們平時所說的野指針),如果給delegate發(fā)消息的話就會引發(fā)奔潰了,而用weak的話,成員變量會自動被賦nil,相比于assign,此時它是更安全的做法。

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

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

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