我們都知道香璃,用assign修飾屬性時这难,當(dāng)屬性所指向的對象被釋放,就造成野指針葡秒,訪問野指針會導(dǎo)致崩潰姻乓,現(xiàn)在我們利用runtime機制來使assign 修飾的@property嵌溢,擁有weak的效果。
主要的方案是蹋岩,當(dāng)一個對象被釋放時赖草,會釋放其擁有的屬性,所以我們利用runtime為NSObject動態(tài)添加屬性剪个,在此屬性被釋放時秧骑,執(zhí)行想要的操作。
具體實現(xiàn)如下:
創(chuàng)建一個執(zhí)行類扣囊,用block初始化它乎折,并且在釋放時執(zhí)行block
//.h
@interface YZLBlockExecutor : NSObject
- (instancetype)initWithBlock:(dispatch_block_t)block;
@end
//.m
@interface YZLBlockExecutor ()
@property (nonatomic, copy) dispatch_block_t block;
@end
@implementation YZLBlockExecutor
- (instancetype)initWithBlock:(dispatch_block_t)block{
if (self = [super init]) {
self.block = block;
}
return self;
}
- (void)dealloc{
if (self.block) {
self.block();
}
}
@end
擴展NSObject
//.h
- (void)yzl_runWhenDealloc:(dispatch_block_t)block;
//.m
- (void)yzl_runWhenDealloc:(dispatch_block_t)block{
YZLBlockExecutor *ex = [[YZLBlockExecutor alloc]initWithBlock:block];
objc_setAssociatedObject(self,@"YZLBlockExecutor", ex, OBJC_ASSOCIATION_RETAIN);
}
具體使用
@interface ViewController ()
@property (assign, nonatomic) NSInteger num;
@property (assign, nonatomic) parent *p;
@end
@implementation ViewController{
dispatch_source_t _source;
}
- (void)viewDidLoad {
[super viewDidLoad];
parent *p = [[parent alloc]init];
self.p = p;
[self.p yzl_runWhenDealloc:^{
NSLog(@"釋放");
// _p = nil; (2)
}];
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(@"訪問:%@",self.p.name);
}
@end
當(dāng)注釋掉(2)時,在viewWillAppear
中執(zhí)行的操作會引起崩潰侵歇,因為self.p
是assign笆檀,而臨時變量p在出viewDidLoad
時就被釋放掉。而不注釋(2)就能正常運行盒至。