iOS 代理為啥要用weak修飾? (刨根問底一)
阿新 • • 發佈:2019-02-02
在開發中我們經常使用代理,或自己寫個代理,而代理屬性都用weak(assign)修飾,看過有些開發者用strong(retain),但並沒發現有何不妥,也不清楚weak(assign)與strong(retain)修飾有何區別
功能實現就行了,考慮這麼多幹嘛~~~我只能哈哈哈
weak
:指明該物件並不負責保持delegate這個物件,delegate這個物件的銷燬由外部控制
@property (nonatomic, weak) id<HSDogDelegate>delegate;
strong
:該物件強引用delegate,外界不能銷燬delegate物件,會導致迴圈引用(Retain Cycles)
@property (nonatomic, strong) id<HSDogDelegate>delegate;
可能你還不太理解,沒關係,下面先舉例,看結果,再分析!
舉例
HSDog類
HSDog.h
:
@protocol HSDogDelegate <NSObject>
@end
@interface HSDog : NSObject
@property (nonatomic, weak) id<HSDogDelegate>delegate;
@end
HSPerson.m
:
#import "HSDog.h"
@implementation HSDog
- (void)dealloc
{
NSLog(@"HSDog----銷燬");
}
@end
HSPerson類
HSPerson.h
:
@interface HSPerson : NSObject
@end
HSPerson.m
:
#import "HSPerson.h"
#import "HSDog.h"
@interface HSPerson()<HSDogDelegate>
/** 強引用dog*/
@property (nonatomic, strong) HSDog *dog;
@end
@implementation HSPerson
- (instancetype)init
{
self = [super init];
if (self) {
// 例項化dog
self.dog = [[HSDog alloc] init];
// dog的delegate引用self,self的retainCount,取決於delegate修飾,weak:retainCount不變,strong:retainCount + 1
self.dog.delegate = self;
}
return self;
}
- (void)dealloc
{
NSLog(@"HSPerson----銷燬");
}
@end
在ViewController實現
:
#import "ViewController.h"
#import "HSPerson.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 例項化person, self對person弱引用,person的retainCount不變
HSPerson *person = [[HSPerson alloc] init];
}
@end
結果
:
weak修飾代理
@property (nonatomic, weak) id<HSDogDelegate>delegate;
執行->列印
:
HSPerson----銷燬
HSDog----銷燬
strong修飾代理
@property (nonatomic, strong) id<HSDogDelegate>delegate;
執行->列印
:
....並未列印,說明HSPerson、HSDog物件沒呼叫dealloc方法,兩個物件未銷燬
這也是我們經常說的記憶體洩露,該釋放的記憶體並未釋放!
分析
:
使用strong
person對dog強引用
@property (nonatomic, strong) HSDog *dog; person
self.dog.delegate又對person強引用,使person的retainCount + 1
@property (nonatomic, strong) id<HSDogDelegate>delegate;
當viewController不對person引用後,dog.delegate對person還強引用著,person的retainCount為1,所以person不會釋放,dog固然也不會釋放,這就是造成迴圈引用的導致記憶體洩露的原因!
- 使用weak
person對dog強引用
@property (nonatomic, strong) HSDog *dog; person
self.dog.delegate只對person弱引用,並未使person的retainCount + 1
@property (nonatomic, weak) id<HSDogDelegate>delegate;
所以當viewController不對person引用後,person的retainCount為0,即person會被釋放,那麼dog也被釋放