请参阅此代码示例:
dispatch_queue_t downloadQueue=dispatch_queue_create("test", NULL);
dispatch_async(downloadQueue, ^{
//do some core data fetching stuff
//create UIImage
//Need to go back to the main thread since this is UI related
dispatch_async(dispatch_get_main_queue(), ^{
if(someView)
{
[someView addSubview:self];
}
}
});
});
dispatch_release(downloadQueue);
如果此代码的主线程部分运行时“someView”不存在,该怎么办?显然这会导致EXC_BAD_ACCESS崩溃,但我想知道处理这种情况的最佳方法是什么。它通常发生在用户导航到需要几秒钟加载的页面时,但随后决定在当前页面仍在加载时返回上一页。
我可以想象在尝试添加子视图之前需要检查某种全局标志,但这看起来很糟糕。
答案 0 :(得分:0)
dispatch_async(downloadQueue, ^{
UIView* v = someView;
现在,如果此时someView
已经不存在,并且如果您使用ARC,则v
为零,您可以测试它。
另一方面,如果存在someView
,并且如果您使用ARC,那么v
是对它的强引用,并且对于块嵌套的其余部分它不会不存在。然后你可以(在那个时刻或者稍后在块的主线程部分中)询问v.window
以发现视图是否仍在界面中;如果没有,就不值得继续。
答案 1 :(得分:0)
// Capture a strong reference to someView, to make sure it's still around later on.
__block UIView *v = someView;
//Need to go back to the main thread since this is UI related
dispatch_async(dispatch_get_main_queue(), ^{
[v addSubview:self]
// Release v (assuming ARC). If nothing else has retained someView, this means
// that someView will be deallocated - but we're on the main thread,
// so that's fine. What we don't want is a background dealloc.
v = nil;
});
OR
// Capture a strong reference to someView, to make sure it's still around later on.
__weak UIView *weakRef = someView;
//Need to go back to the main thread since this is UI related
dispatch_async(dispatch_get_main_queue(), ^{
// This is thread-safe because someView should only be de-alloced on the main thread.
// consequently our access to weakRef is safe.
UIView *strongRef = weakRef;
[strongRef addSubview:self];
});
你不能做的就是这个。
UIView *strongRef = whatever;
dispatch_async(downloadQueue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
[someView addSubview:self]
});
// If, by the time we get here, the dispatch to the main queue has already run,
// then we will send a release to someView on a background thread. If it's the last
// remaining reference - and it might be, unlikely as it is, then we just dealloced
// a UIView in the background. This is bad.
});