0

在下面粘贴的代码中,如何检查/确保在执行对​​“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

4 回答 4

1

你有什么理由使用__block而不是__weak?您似乎没有更改 的值self(无论如何这将是一件奇怪的事情),并且使用弱引用既可以防止任何保留周期,又可以确保如果pSelf对象被释放,您的变量将指向nil并且您会'不要冒一个糟糕的访问崩溃的风险。

于 2012-09-10T05:59:02.783 回答
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),但也有在保留/释放行为中明确表示没有害处,因为它使代码更清晰(恕我直言)。

于 2012-09-11T00:18:26.897 回答
0

来自苹果开发者网站:

__block 变量存在于变量的词法范围和在变量的词法范围内声明或创建的所有块和块副本之间共享的存储中。因此,如果在帧内声明的块的任何副本在帧结束后仍然存在(例如,通过在某处排队以供以后执行),则存储将在堆栈帧的破坏中幸存下来。给定词法范围内的多个块可以同时使用一个共享变量。

这意味着它不会被释放。


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

于 2012-09-10T05:00:10.717 回答
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];
    });
});

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

于 2012-09-12T05:05:39.593 回答