weak的一般用法
关于属性,我们声明的时候会使用Strong与Weak。但是二者在使用的时候有什么区别呢。
1、在使用xib 或者SB 拖控件的时候我们都会看到系统帮我们声明的是:@property (weak, nonatomic) IBOutlet UILabel *lalbel;
,首先这个控件是用weak来声明的。所以一旦执行了[self.lalbel removeFromSuperview];lalbel
的地址为nil
,只要在使用该控件过程中,没有执行removeFromSuperview
,该控件会一直存在在内存里,不会被释放。
当我们用使用代码来声明一个weak
时,
系统会自动识别,在分配好内存好因为没有强引用,只有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。