weak与strong的区别以及解决NSTimer循环引用的问题

weak的一般用法

关于属性,我们声明的时候会使用Strong与Weak。但是二者在使用的时候有什么区别呢。

1、在使用xib 或者SB 拖控件的时候我们都会看到系统帮我们声明的是:@property (weak, nonatomic) IBOutlet UILabel *lalbel;,首先这个控件是用weak来声明的。所以一旦执行了[self.lalbel removeFromSuperview];lalbel的地址为nil,只要在使用该控件过程中,没有执行removeFromSuperview,该控件会一直存在在内存里,不会被释放。

当我们用使用代码来声明一个weak时,

image.png

系统会自动识别,在分配好内存好因为没有强引用,只有weak引用,会直接释放掉,所以此刻打印self.label 是nil。
我们需要这样做:

UILabel *lable =[[UILabel alloc]init];
    self.label = lable;

此刻 打印self.label 是有地址的。
但是 如果该控件没有被加到父视图中,出了该作用域,依然是没有地址的。

2、 使用strong 来修饰,不管有没有加到父视图里,该控件的地址会一直存在。因为它一直被 该ViewController强引用。只有ViewController 执行了delloc 之后,才会释放。

总结:

如果要严格控制内存管理,对于不常用或者中间可能不需要被释放内存的属性,我们使用weak来修饰,但是要严格注意是不是被父视图所引用。

如果不是那么严格,所有的控件属性通过strong来修饰,地址就会永远存在,不用担心突然被释放的问题。

如果控件在使用过程中一直存在,那么使用strong即可。如果控件在使用过程中会被移除,那么使用weak,可以节省内存

NSTimer解决循环引用的问题

timer使用block方式添加Target-Action

这里我们需要自己在NSTimer的分类中添加类方法:

@implementation NSTimer (BlcokTimer)

+ (NSTimer *)bl_scheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void (^)(void))block repeats:(BOOL)repeats {
    
    return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(bl_blockSelector:) userInfo:[block copy] repeats:repeats];
}

+ (void)bl_blockSelector:(NSTimer *)timer {
    
    void(^block)(void) = timer.userInfo;
    if (block) {
        block();
    }
}
@end

通过block的方式,获取action,实际的target设置为self,即NSTimer类。这样我们在使用timer时,由于target的改变,就不再有循环引用了。 使用中还需要注意block可能引起的循环引用,所以使用weakSelf:

__weak typeof(self) weakSelf = self;

self.timer = [NSTimer bl_scheduledTimerWithTimeInterval:1 block:^{
     [weakSelf changeText];
} repeats:YES];

虽然没有了循环引用,但是还是应该记得在dealloc时释放timer。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容