最近,我自己也是刚刚找到工作,也是面试了很多家公司。也尝试着总结一下,这是我的第一篇面试之后的总结,那么前戏不多,直奔主题,小伙们似乎已经等不及啦。

我们开发的过程中经常的使用代理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也就被释放啦。