始終覺得,好記性不如爛筆頭,寫博客還是非常有必要的,不但可以記錄自己學習到的知識,也還可以和別人一起分享。最重要的就是,整理博客的過程,也是再次學習的一個過程。。。
最近項目完成差不多了,得以空閑,打算重新開始博客之路,并要堅持下去。好吧,不扯淡了,開始我的第一篇博客。
平常寫代碼,代理再常見不過了,寫了n次delegate,可是為啥用weak,總是一知半解,今天項目中再次用的代理,寫weak的時候,我仔細研究了一下,打算記錄下來,和大家一起分享。
1.為什么要用weak而不是用strong呢,因為weak是弱引用,weak屬性的變量是不為其所屬對象持有的,并且在該變量被銷毀之后,此weak變量的值會自動被賦值為nil,而strong會持有著這個屬性,不會被銷毀。
文字描述可能不是那么好理解,好了,上代碼:
舉個??
我創建了兩個類,一個是學生類student,一個是教師類teacher,給教師類添加個delegate的屬性,并且讓學生作為教師的代理。如代碼:
#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的修飾下,運行結果為:
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后,無任何打印,說明沒有將對象釋放,該釋放的時候沒有釋放,這就是我們平時所說的內存泄漏。
之所以會出現這個問題,就是因為strong的強引用,再直觀點的圖為下:
2.講解完strong和weak的區別了,但是有的會問,那assign也不會強持有該屬性啊,是否也可以使用assign?
先來說一下assign:assign屬性一般是對C基本數據類型成員變量的聲明,當然也可以用在對象類型成員變量上,只是其代表的意義只是單純地拷貝所賦值變量的值。即如果對某assign成員變量B賦值某對象A的指針,則此B只是簡單地保存此指針的值,且并不持有對象A,也就意味著如果A被銷毀,則B就指向了一個已經被銷毀的對象,如果再對其發送消息會引發崩潰。
大多數情況下,修飾delegate,既可以用weak,又可以用assign。因為在幾乎所有場景下,delegate所指向的對象C的生存期都是覆蓋了delegate成員變量本身所在的對象D的生存期的,所以,在D的生存期內,C所使用的D的指針都是有效的,所以這個時候使用assign是沒有關系的。
但是,用weak是更加安全些的,為什么這么說呢?舉個??:
用上圖的代碼來說,viewController擁有一個student對象以供業務的使用,student與viewController是一對一的關系,如果viewController被銷毀,則其對應的student也就沒有存在的意義了,且viewController的銷毀也會馬上引發student的銷毀。所以student的delegate成員變量內存管理屬性聲明為assign是沒有問題的,但是如果delegate是assign屬性,在viewController銷毀的時候,student因為仍然被其他地方引用而導致其此時并沒有跟隨viewController一起銷毀,那么此時delegate指向了一個已經被銷毀的對象(我們平時所說的野指針),如果給delegate發消息的話就會引發奔潰了,而用weak的話,成員變量會自動被賦nil,相比于assign,此時它是更安全的做法。