如果我们用对象A的属性(strong修饰)去指向一个objc对象B。那么如果对象A没有被释放对象B永远不会被释放。如果对象B是一个view当我们已经把B添加到视图上的时候。有些情况下可能希望提前释放掉对象B。这种情况下我们可以使用weak修饰符指向来达到可以提前释放的效果。
代码如下
@interface ViewController ()
//使用weak修饰weakView
@property (nonatomic, weak) UIView *weakView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.weakView = [[UIView alloc]initWithFrame:CGRectMake(0, 20, 300, 40)];
_weakView.backgroundColor = [UIColor redColor];
[self.view addSubview:_weakView];
}
通过结果发现weakView并没有强引用新创建的View。新创建的View呗创建出来之后直接被释放了。这种方法并不可取。
我们更换一种方法
@interface ViewController ()
@property (nonatomic, weak) UIView *weakView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个cacheView指向新创建的view
UIView *cacheView = [[UIView alloc]initWithFrame:CGRectMake(0, 20, 300, 40)];
//通过一个weak修饰的属性指向cacheView
self.weakView = cacheView;
_weakView.backgroundColor = [UIColor redColor];
[self.view addSubview:_weakView];
}
发现这种可以保证在属性指向过程中不会强引用cacheView,又能保证可以在必要的时候提前释放掉view
验证自动释放池外是否可以通过weak指针正常获取到cacheView
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSLog(@"%@",self.weakView);
}
控制台输出为:
2018-02-01 15:08:29.019353+0800 WeakView[1806:133550] <UIView: 0x7f91a1d09f60; frame = (0 20; 300 40); layer = <CALayer: 0x604000037ca0>>
原理分析:
1.现在的绝大多数开发都是使用ARC来进行开发。因为使用了自动释放池。我们在自动释放池中创建的对象默认都是使用strong修饰的。但是会在自动释放池外autorealease掉。如果直接用weak属性来存储新创建的view。那么会直接使用weak对象来指向。直接被释放掉了。
2.我们先用一个临时指针指向,通过[self.view addSubview:_weakView]这句代码会对weakView进行强引用。然后用weak指针指向。这样weakView既不会被自身强引用。同时也可以通过weak指针来获取对象。