Objective c 我什么时候释放这个区块?

Objective c 我什么时候释放这个区块?,objective-c,memory-management,objective-c-blocks,grand-central-dispatch,Objective C,Memory Management,Objective C Blocks,Grand Central Dispatch,我正在看这个线程中的一些代码。我想知道,如果块异步执行某些操作,那么应该何时释放块 假设我有这样的代码: - (void)testMethod:(id)parameter { dispatch_block_t block = ^{ SomeAsyncTask *t = [SomeAsyncTask withCompletionBlock:^{ [parameter doAction];

我正在看这个线程中的一些代码。我想知道,如果块异步执行某些操作,那么应该何时释放块

假设我有这样的代码:

- (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中的完成块将保留参数,以便安全地释放该块吗?

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


编辑以添加:顺便问一下,为什么不使用
dispatch\u after()
,如您链接到的问题的答案所示?

我可以尝试传递一个带有参数的数组

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

首先,不清楚您的意思是
performSelector:withObject:
还是
performSelector:withObject:afterDelay:
,因为
performSelector:withObject:
是一个直接同步调用,所以
[自执行选择器:@selector(runBlock:)withObject:block\n]
[自运行块:块]
相同。我假设它是
performSelector:withObject:afterDelay:
,因为
performSelector:withObject:
不太有趣

一步一步地看
performSelector:withObject:afterDelay:
保留其参数,因此您可以在向其提供块后释放它。和
performSelector:…
通过其选择器的性能保留它。因此,在
运行块期间,该块是有效的,因为它仍然由
性能选择器保留:…
。在执行块期间,它仍然有效(因为它仍然在执行
runBlock
的过程中)
doSomethingAsynchronouslyWithCompletionBlock如果是异步的,则必须保留其参数。等等

但你不需要这样看。仔细考虑之后,您将意识到内存管理规则的制定是为了您不必担心其他代码会做什么,只需担心本地需要什么

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

例如,在
doWork
中,您只关心需要使用该块多长时间。因为在
performSelector:…
之后不需要它,所以您可以安全地释放它。
performSelector:…
可以异步处理它,这并不重要;您甚至可能不知道它是异步的(例如,您可能正在选择一个未知的方法进行动态调用)。关键是,它的作用无关紧要。为什么?因为
performSelector:…
不会假定参数的有效时间比您调用它的时间长。因此,如果它需要保留它的时间长(而且确实如此),它必须保留它(但您不需要知道这一点).只要它需要,它就会保留它


类似地,
runBlock
可以假定它提供的参数在调用期间有效。因为它不需要将参数保留更长时间(它所做的只是调用该块),所以它不需要保留它。该块不会改变这一点。为什么?同样,因为该块不采用其参数(包括区块本身)在调用后是有效的,因此
runBlock
不需要保证它。如果块调用
doSomethingAsynchronouslyWithCompletionBlock
,这很好。
doSomethingAsynchronouslyWithCompletionBlock
不假定任何东西在其调用之外是有效的,因此如果它确实是异步的,它必须将它保留在某个地方。等等>如果在performSelector之后释放,我仍然会遇到同样的问题。runBlock方法必须保留块,而块必须释放自己。为什么
-runBlock:
必须保留块?主要问题仍然存在。内存管理应该在本地完成。您不需要采用全局透视图。Ju确保每个部分都做了正确的事情,而整个部分都会做正确的事情。“部分”是指局部变量或参数时的方法或函数。“部分”是指实例变量时的类。什么是不同步的?延迟后执行与调用方不同步(
+doWork
),但在延迟之后,选择器的实际性能(
+runBlock:
)与执行后延迟内部同步,并且这些内部保证在执行选择器之前保留参数。这不是您的问题。确保接收器和参数在执行选择器之前保留是Cocoa的问题。不做任何更改。首先,您只编辑了al可选的代码片段,一直不清楚,因为它在语法上是无意义的。如果块中有一个函数或方法与另一个块异步,则该函数或方法负责复制并最终释放其块。传递给
-performSelector…
的块将保留足够长的时间.启动异步进程的块本身不会重新启动