确保该对象存在于块的延迟调用中

时间:2012-09-10 04:53:11

标签: iphone ios ipad grand-central-dispatch

在下面粘贴的代码中,当执行对“showResultToUser”的调用并且我不会调用已发布的对象时,如何检查/确保对象仍然存在?

__block MyClass pSelf = self;

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^
{
    [pSelf doSomeBackgroundWork];
    dispatch_async(dispatch_get_main_queue(), ^
    {
        [pSelf showResultToUser];
    });
});

4 个答案:

答案 0 :(得分:1)

您使用__block而不是__weak是否有任何理由?您似乎没有更改self的值(这无论如何都是奇怪的事情)并且使用弱引用会阻止任何保留周期并确保如果pSelf对象是发布后,您的变量将指向nil,您不会冒着访问崩溃的风险。

答案 1 :(得分:0)

来自苹果开发者网站:

  

__块变量存在于存储中,该存储在变量的词法范围与在变量的词法范围内声明或创建的所有块和块副本之间共享。因此,如果在帧内声明的块的任何副本存活超出帧的结尾(例如,通过在某处排队以便稍后执行),则存储将在堆栈帧的破坏中存活。给定词法范围内的多个块可以同时使用共享变量。

这意味着它不会被释放。


除此之外,没有办法检查你的句柄是否引用了一个有效的变量,因为如果 被释放,它可能已被另一个有效(但不同)的变量重用,你的'测试'会说好的。

答案 2 :(得分:0)

我认为这个问题被__block分配行为弄糊涂了,pSelf变量本身是否处于稳定存储中(它是:__block导致它在堆上分配,即使它是在堆栈帧内声明的)。更重要的是,在没有ARC(你说你没有使用)的情况下,你是在将块传递给dispatch_async()之前显式保留这些对象,然后从块中释放它们。请参阅dispatch_async的手册页并查找标记为“COMPLETION CALLBACKS”的部分,其中创建async_read()函数作为示例 - 查看目标队列如何保留然后释放?遵循相同的模式将使您免于麻烦。

请注意,块内的ObjC实例变量对象会自动“免费”获取保留行为(http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html)但是在保留/释放行为中明确没有任何害处,因为它使代码更清晰(恕我直言)。

答案 3 :(得分:0)

您可以通过删除__block限定变量来阻止对象被释放:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^
{
    [self doSomeBackgroundWork];
    dispatch_async(dispatch_get_main_queue(), ^
    {
        [self showResultToUser];
    });
});

您可能会不必要地延长引用对象的生命周期,但如果没有其他内容保留它,它将在内部块执行结束时释放。