Ste*_*her 13 ios automatic-ref-counting
如果我向弱对象发送消息会怎样?发送消息是否拥有该对象并将其保存在内存中直到返回?
我在考虑这种模式:
__weak MyObject *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf doSomeAction];
});
Run Code Online (Sandbox Code Playgroud)
假设weakSelf在发送消息时为非零,是否可以在doSomeAction工作时解除分配,或者保证在doSomeAction返回之前保持有效?
Lil*_*ard 19
读数执行上的对象的左值一个左值到右值转换时,会发生.
- 对于
__weak对象,保留当前的指针对象,然后在当前的完整表达式结束时释放.这必须在分配和指针的最终版本方面以原子方式执行.
传递弱引用会对变量执行左值到右值转换,这意味着弱引用的值将被保留,然后在当前完整表达式(基本上是语句)结束时释放.它基本上等同于分配一个强变量,其范围仅适用于当前语句,然后传递该强变量.
这里要说的是,如果你想要一次发送一个弱变量,而不再触摸它,你就不关心在弱引用结束的情况下评估方法参数的副作用nil,然后去提前并直接传达弱参考.但是如果你需要两次引用弱引用(在单独的语句中),或者评估参数的副作用很重要,那么你应该nil在继续之前分配一个强变量并测试non .
你问:
假设
weakSelf是不nil发送消息时,同时也可能被释放doSomeAction是工作还是保证仍然有效,直到doSomeAction回报?
这种 ARC 行为随着时间的推移而改变。但是现在,weak只要删除最后一个强引用,就可以释放引用。
因此,请考虑以下事项:
- (void)dealloc {
NSLog(@"%s", __FUNCTION__);
}
- (void)startBackgroundOperation {
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakSelf doSomeAction];
[NSThread sleepForTimeInterval:5];
[weakSelf doSomeAction2];
});
}
- (void)doSomeAction {
NSLog(@"%s", __FUNCTION__);
}
- (void)doSomeAction2 {
NSLog(@"%s", __FUNCTION__);
}
Run Code Online (Sandbox Code Playgroud)
如果您有一些代码调用startBackgroundOperation并让对象在doSomeAction和之间的中间时间被释放doSomeAction2,您将看到前者将被调用而后者不会。即如果没有更多的强引用,对象可以在块的中间被释放。
所以,如果你想要弱引用,但想要一个“全有或全无”的行为,从而在闭包期间保留它,我们执行被戏称为“ weakSelf-strongSelf舞蹈”的动作:
- (void)startBackgroundOperation {
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
typeof(self) strongSelf = weakSelf; // establish just-in-time strong reference (if `weakSelf` is not yet `nil`)
[strongSelf doSomeAction];
[NSThread sleepForTimeInterval:5];
[strongSelf doSomeAction2];
});
}
Run Code Online (Sandbox Code Playgroud)
这将确保该块有一个weak引用,但如果它在达到 的赋值时没有被释放strongSelf,那么它将在该块的持续时间内建立并维护一个强引用。
就其价值而言,这种weakSelf-strongSelf模式在取消引用 ivars 时是必不可少的->(避免竞争条件weakSelf)。
例如
- (void)badDeferenceExample {
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (!weakSelf) { return; }
NSInteger value = weakSelf->_someIVar; // this is race and can crash!!!
...
});
}
- (void)properDeferenceExample {
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
typeof(self) strongSelf = weakSelf; // establish just-in-time strong reference (if `weakSelf` is not yet `nil`)
if (!strongSelf) { return; }
NSInteger value = strongSelf->_someIVar; // this is safe
...
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
899 次 |
| 最近记录: |