什么是代理?
iOS开发,OC是常用开发语言,但是OC仅仅是单继承,但是我们可以用代理来替代,那么什么是代理呢? 通俗一点讲就是我的事情,我只定义标准(协议),具体怎么做,让别人(代理商)去做。
代理三步骤
协议:用来指定代理双方可以做什么,必须做什么。
代理:根据指定的协议,完成委托方需要实现的功能。
委托:根据指定的协议,指定代理去完成什么功能。
iOS开发中一个可以可以由多个代理实现,一个代理也可实现多个协议,是不是有点像多继承了。
下面用一个例子来说明:
###声明一个协议
@protocol testViewDelegate <NSObject>
-(void)sendValue:(NSString *)str;
@end
###委托方
NS_ASSUME_NONNULL_BEGIN
@interface testViw : UIView
@property(nonatomic,weak)id<testViewDelegate>delegate;
@property(nonatomic,strong)UIButton *btn;
@end
NS_ASSUME_NONNULL_END
###委托方@implementation实现部分
#import "testViw.h"
@implementation testViw
-(instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self addUI];
}
return self;
}
-(void)addUI{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(0, 110, 100, 200);
btn.backgroundColor = [UIColor grayColor];
[self addSubview:btn];
[btn addTarget:self action:@selector(clickTap) forControlEvents:UIControlEventTouchUpInside];
}
-(void)clickTap{
if ([self.delegate respondsToSelector:@selector(sendValue:)]) {
[self.delegate sendValue:@"name"];
}
}
@end
secViewController就是代理者
#import "secViewController.h"
#import "testViw.h"
@interface secViewController ()<testViewDelegate>
@end
@implementation secViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"secView";
self.view.backgroundColor = [UIColor whiteColor];
testViw *test = [[testViw alloc]initWithFrame:CGRectMake(0, 0, 375, 568)];
[self.view addSubview:test];
test.delegate = self;
}
-(void)sendValue:(NSString *)str
{
NSLog(@"%@",str);
}
-(void)dealloc{
NSLog(@"sec dealloc");
}
@end
回到标题问题,正常咱们退出secViewController时候,dealloc方法打印
2020-09-07 15:02:36.702238+0800 test1[5865:348779] sec dealloc
如果用strong修饰就不会打印了,说明存在内存泄漏了。为什么呢?问题就处在这test.delegate = self;这句代码,由于sec控制器引用了tstViw对象,让tstViw引用计数加1, test.delegate = self;执行后,tstViw对象又引用了sec控制器(self),所以这就形成了循环引用,解决办法相信大家已经清楚了,标题以及说明了一切。但是为什么也不建议用assign呢,其实这个考虑安全性,正常也可以使用,assign修饰对象在前面也特意写了一篇文章,assign修饰的对象存在堆区,对象释放指针不会清空,如果在使用对象就容易崩溃,至于为什么weak不会,是由于runtime底层原理,存在一个哈希表,系统会自动清空指针的原因,可以看看我以前文章“assign修饰对象会怎么样?”