说明一下造成循环引用的场景,viewController持有某个view,view中持有block,block内部引用vc,造成的循环引用。在arc的环境下使用__weak即可解决问题,但是mrc中不能使用weak关键字(其实是可以在项目配置中设置的,但是考虑到老项目一般都没有开放mrc使用weak的配置,所以不使用weak),使用__block即可。
//view.h
@interface BlockView : UIView
@property(nonatomic, copy)void(^dismissCallback)(void);
@end
//view.m
@implementation BlockView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(jk_tapAction)];
[self addGestureRecognizer:tap];
[tap release]; tap = nil;
}
return self;
}
- (void)dealloc{
[super dealloc];
}
- (void)jk_tapAction{
if (self.dismissCallback) {
self.dismissCallback();
}
self.backgroundColor = [UIColor blueColor];
}
@end
//vc.m
@interface BlockViewController ()
@property(nonatomic, retain)UILabel *titleLabel;
@end
@implementation BlockViewController{
BlockView *_redView;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
self.titleLabel.text = @"title";
[self.view addSubview:self.titleLabel];
__block typeof(self) weakSelf = self;
_redView = [[BlockView alloc] initWithFrame:CGRectMake(100, 200, 100, 100)];
_redView.backgroundColor = [UIColor redColor];
_redView.dismissCallback = ^{
//如果不使用weakSelf则无法进入dealloc
weakSelf.titleLabel.text = @"changed";
};
[self.view addSubview:_redView];
}
- (void)dealloc{
[_redView release]; _redView = nil;
[_titleLabel release]; _titleLabel = nil;
[super dealloc];
}
demo在这里https://gitee.com/Jack_1993/mrc_-playground
希望能够对在arc时代开始做iOS的大家有帮助:)
网友评论