最近,我自己也是刚刚找到工作,也是面试了很多家公司。也尝试着总结一下,这是我的第一篇面试之后的总结,那么前戏不多,直奔主题,小伙们似乎已经等不及啦。
我们开发的过程中经常的使用代理delegate来替我们做事,而怎么修饰代理属性呢,说实话之前我还用过strong,却也一样实现功能,那时候我觉得有什么的,搞得出来都一样,想想都好笑。这个问题也是面试官的钟爱问题了。
现在,这里郑重庄严的说一下delegate一定用weak修饰!!!
下面,说一下原因:
weak:修饰对象只是指明该对象,并不负责保持这个对象,对象的销毁是由外部控制的。
@property (nonatomic, weak) id<LYSunDelegate>delegate;
strong:修饰对象是对该对象进行强引用,外界不能销毁该对象,会导致循环引用(Retain Cycles)
@property (nonatomic, strong) id<LYSunDelegate>delegate;
可能小白看到了不会懂,没关系,下面举个栗子。
首先创建一个LYSun类(LY是我骚气的名字),这是我的.h文件:
@protocol LYSunDelegate <NSObject>
@end
@interface LYSun : NSObject
@property (nonatomic, weak) id<LYSunDelegate>delegate;
@end
下面是.m文件:
#import "LYSun.h"
@implementation LYSun
- (void)dealloc
{
NSLog(@"LYSun----销毁");
}
@end
然后创建一个LYPerson 类:
@interface LYPerson : NSObject
@end
#import "LYPerson.h"
#import "LYSun.h"
@interface LYPerson()<LYSunDelegate>
/** 强引用dog*/
@property (nonatomic, strong) LYSun *sun;
@end
@implementation LYPerson
- (instancetype)init
{
self = [super init];
if (self) {
// 实例化dog
self.sun = [[LYSun alloc] init];
// sun的delegate引用self,self的retainCount,取决于delegate修饰,weak:retainCount不变,strong:retainCount + 1
self.sun.delegate = self;
}
return self;
}
- (void)dealloc
{
NSLog(@"LYPerson----销毁");
}
@end
ViewController 的实现:
#import "ViewController.h"
#import "LYPerson.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 实例化person, self对person弱引用,person的retainCount不变
LYPerson *person = [[LYPerson alloc] init];
}
@end
下面就是weak 和 strong 对比的结果:
weak修饰代理:
@property (nonatomic, weak) id<LYSunDelegate>delegate;
打印:
LYPerson----销毁
LYSun----销毁
strong修饰代理:
@property (nonatomic, strong) id<LYSunDelegate>delegate;
并未有任何的打印,说明LYPerson、LYSun对象调用dealloc方法时,两个对象并没有销毁,这其实最容易产生内存泄漏,这两个对象申请的内存空间,用完之后并没有释放掉,仍然占用。
分析:
使用strong的情况如下:
//这个是LYPerson 类的属性,对 sun 强引用
@property (nonatomic, strong) LYSun *sun;
//这个是LYSun 类的代理属性
@property (nonatomic, strong) id<LYSunDelegate>delegate;
/*
在LYPerson.m 中self.sun.delegate 又对 self(就是person)请引用,person的retainCount + 1
*/
self.sun.delegate = self;
当viewController不对person引用后想释放person的时候,发现这时sun.delegate对person还强引用着呢,person的retainCount为1,所以person不会释放,sun固然也不会释放,这就是造成循环引用导致的内存泄漏的原因。
使用weak修饰的情况如下:
//区别在于:delegate是weak修饰,所以这里self.sun.delegate对person是弱引用,所以person 的retainCount 不会+1 ,此时retainCount为0
self.sun.delegate = self;
那么,很显然了,当viewController 不对person引用之后,person的retainCount 为 0 ,当然可以释放啦,那么person就被释放了,sun也就被释放啦。