我什么时候释放此块



我正在查看此线程中的一些代码 如何在延迟后触发块,例如 -performSelector:withObject:afterDelay:?。 我想知道,如果块异步执行某些操作,何时应该释放该块?

假设我有如下所示的代码:

- (void)testMethod:(id)parameter
{
    dispatch_block_t block = ^{
         SomeAsyncTask *t = [SomeAsyncTask withCompletionBlock:^{
                                 [parameter doAction];
                             }];    
    };
    [self performSelector:@selector(executeBlock:)
            onThread:backgroundThread
               withObject:block
            waitUntilDone:NO];
    dispatch_release(block); //I can release the block here because performSelector      retains the block
}
- (void)executeBlock:(id)block
{
    block();
}

那么,关键是,SomeASyncTask 中的完成块将保留参数,以便安全地释放该块?

Ken Thomases的回答是正确的。我想对你的评论作出更详细的回应。

首先,不清楚你的意思是performSelector:withObject:还是performSelector:withObject:afterDelay:,因为performSelector:withObject:是直接同步调用,所以[self performSelector:@selector(runBlock:) withObject:block_];[self runBlock:block_]相同。我假设它是performSelector:withObject:afterDelay:,因为performSelector:withObject:不那么有趣。

一步

一步地看。 performSelector:withObject:afterDelay:保留其参数,因此您可以在将块交给它后释放它。performSelector:...通过其选择器的性能保留它。所以在runBlock期间,区块是有效的,因为它仍然被performSelector:...保留。在块的执行过程中,它仍然有效(因为它仍在执行runBlock 内)。 如果doSomethingAsynchronouslyWithCompletionBlock是异步的,则必须保留其参数。等等。

但你不需要这样看。一旦你仔细考虑了它,你就会意识到内存管理规则是这样你就不需要担心其他代码做什么,只需要担心你在本地需要什么

内存管理规则归结为以下条件:每个函数/方法都希望其参数在被调用时有效(这通常意味着在函数调用的持续时间内,因为调用函数在此期间不运行,那么它怎么会变得无效,除非这个函数做了一些间接删除它的事情(比如从字典中删除)? 并且对函数调用后它将保持有效期没有任何期望。就是这样。一切都由此而来。

例如,在您的doWork中,您只关心需要使用该块多长时间。由于performSelector:...后您不需要它,因此您可以安全地释放它。performSelector:...可能会异步使用它做一些事情并不重要;您甚至可能不知道它是异步的(例如,您可能正在选择一种未知的方法来动态调用)。关键是,它做什么并不重要。为什么?因为performSelector:...假定参数的有效时间不会超过您调用它的时间。因此,如果它需要保留更长时间(确实如此),它必须保留它(但你不需要知道这一点)。只要它需要它,它就会保留它。

同样,runBlock可以假定给出的参数在其调用期间有效。由于它不需要将其保留更长时间(它所做的只是调用块),因此它不需要保留它。块不会改变这一点。为什么?同样,因为块在调用后不假定其参数(包括块本身)有效,因此runBlock不需要保证它。如果块调用doSomethingAsynchronouslyWithCompletionBlock,那很好。 doSomethingAsynchronouslyWithCompletionBlock 不假定任何内容在其调用之外都是有效的,因此如果它确实是异步的,则必须将其保留在某个地方。等。

您可以在调用 -performSelector:withObject:afterDelay: 后立即释放它。(我假设你的意思是使用延迟后的变体。像往常一样,您负责内存管理,其他代码负责其内存管理。这是另一种说法,-performSelector:withObject:afterDelay:必须保留接收器和传入的对象,直到执行选择器之后。

编辑添加:顺便说一下,你为什么不使用你所链接的问题的答案中所示的dispatch_after()

我可能会尝试传递带有参数的数组。

最新更新