我见过以下用法:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//code to be executed on the main queue after delay
[self doSometingWithObject:obj1 andAnotherObject:obj2];
});
但不应该在街区使用弱自我吗?
__weak typeof(self) weakSelf = self;
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//code to be executed on the main queue after delay
[weakSelf doSometingWithObject:obj1 andAnotherObject:obj2];
});
我对GCD和Blocks很新,并尝试找出最正确的用法。非常感谢关于这一点的任何指导。
答案 0 :(得分:9)
这取决于所需的行为。
第一种语法(在块中引用dispatch_after
)将保持对视图控制器的强引用,直到doSometingWithObject
触发并weakSelf
成功运行。即使与该视图控制器关联的视图在中间期间被解除,也会发生这种情况。
因此,只有在您绝对需要运行该方法的情况下才使用此模式,即使在与该视图控制器关联的视图被解除之后也是如此。例如,如果该方法正在更新某些模型对象,则将某些内容保存到持久存储,发布一些网络请求等等。
第二种语法(weakSelf
模式)不会保持对视图控制器的强引用,因此如果与块视图控制器关联的视图在块运行时被解除,则视图控制器将被释放,nil
将doSometingWithObject
,因此weakSelf
将不会被调用。 (显然,如果视图尚未被解除,视图控制器将不会被释放,nil
将不会weakSelf
并且将调用该方法。)
如果视图尚未被解除,则只需要调用相关方法即可。例如,如果方法的唯一目的是更新该视图上的某个UI对象,那么如果视图已被解除,您显然不需要调用该方法。在这种情况下,您通常更喜欢使用weakSelf
,以便在不再需要时立即释放视图控制器。
为了完整起见,实际上有这种模式的第三种排列,有时(开玩笑地)称为strongSelf
/ __weak typeof(self) weakSelf = self;
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//code to be executed on the main queue after delay
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomethingWithObject:obj1 andAnotherObject:obj2];
[strongSelf doSomethingElseWithObject:obj1];
}
});
“舞蹈”:
self
此模式与第二个示例非常相似,如果取消分配nil
,则不会调用方法。当您需要弱引用时使用此模式,但是(a)您需要确保在块运行时不释放它;或(b)当你需要测试是否# Call with year month day
# e.g. convert_date_to_long 2015 01 01
function convert_date_to_long() {
date="${1}${2}${3}"
let long_date=$date
if [[ $long_date -gt 0 ]]; then
echo "Numeric date: ${long_date}"
fi
}
时,但是要避免竞争条件。
答案 1 :(得分:2)
指向self的弱指针用于防止保留周期。第一个代码段中没有保留周期的风险。
如果您的对象要保留保留对象的块,则保留周期将是一个问题,和如果您的对象仅在释放块本身时释放该块。在这种情况下,这些条件都不适用。
dispatch_after()
将在指定时间后运行提供的块,然后释放块。释放块不依赖于您的对象被释放。没有保留周期。
答案 2 :(得分:-2)
使用块的更好部分是这样的:
__weak typeof(self) weakSelf = self;
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//code to be executed on the main queue after delay
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doSometingWithObject:obj1 andAnotherObject:obj2];
});
在块内创建__strong
引用不会增加内存引用计数。一旦该块完成,它将被释放。
https://dhoerl.wordpress.com/2013/04/23/i-finally-figured-out-weakself-and-strongself/