美文网首页
如何让assign 修饰的@property,拥有weak的效果

如何让assign 修饰的@property,拥有weak的效果

作者: 水水兔 | 来源:发表于2020-01-13 17:22 被阅读0次

我们都知道,用assign修饰属性时,当属性所指向的对象被释放,就造成野指针,访问野指针会导致崩溃,现在我们利用runtime机制来使assign 修饰的@property,拥有weak的效果。

主要的方案是,当一个对象被释放时,会释放其拥有的属性,所以我们利用runtime为NSObject动态添加属性,在此属性被释放时,执行想要的操作。
具体实现如下:
创建一个执行类,用block初始化它,并且在释放时执行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

当注释掉(2)时,在viewWillAppear中执行的操作会引起崩溃,因为self.p是assign,而临时变量p在出viewDidLoad时就被释放掉。而不注释(2)就能正常运行。

相关文章

网友评论

      本文标题:如何让assign 修饰的@property,拥有weak的效果

      本文链接:https://www.haomeiwen.com/subject/splnactx.html