recursion块太早解除分配

我已经写了一个recursion块遵循这些准则:

NSMutableArray *groups = [NSMutableArray arrayWithArray:@[@"group1", @"group2", @"group3", @"group4"]; __block CommunicationCompletionHandler completion = [^{ [groups removeObjectAtIndex:0]; if ([groups count] > 0) { // This will send some information to the network, and calls the completion handler when it receives a response [mySocket saveGroup:groups[0] completion:completion]; } } copy]; // Removing copy here doesn't work either [mySocket saveGroup:groups[0] completion:completion]; 

saveGroup:completion:方法中,我将完成处理程序添加到数组中:

 self.completionHandlers[SaveGroupCompletionHandlerKey] = [completion copy]; 

而当我收到一个响应,我调用下面的方法( key是在这种情况下SaveGroupCompletionHandlerKey ):

 - (void)performCompletionHandlerForKey:(NSString *)key { if (self.completionHandlers[key]) { ((CommunicationCompletionHandler)self.completionHandlers[key])(); [self.completionHandlers removeObjectForKey:key]; } } 

问题是完成处理程序只被调用一次。 removeObjectForKey:块取消分配。 如果我取消注释该行,一切工作正常。 我不知道如何数组有最后一个引用这个块,因为我添加一个copy (我相信正在优化retain )。

为了清楚起见,应用程序的stream程是:

  • 通过networking发送第一组数据
  • 接收回应
  • 呼叫完成处理程序
  • 在完成处理程序中,发送下一个组的数据(这是recursion部分)。

这里有谁能指出我做错了什么?

-performCompletionHandlerForKey: 执行完block 之后 ,你从你的字典中删除了完成处理程序,这意味着处理程序在一次运行后总是会从字典中移除。

而是将块存储在临时variables中,并在执行块之前将其从字典中删除。

顺便说一句,删除弱引用的build议是错误的。 由于您的代码现在写入,您的代码块将永远不会被释放。 典型的块recursion模式是这样的:

 __weak __block MyBlock weakHandler; MyBlock handler = ^ { if (foo) { MyBlock strongHandler = weakHandler; [bar asyncOperationWithCompletion:strongHandler]; } }; weakHandler = handler; [bar asyncOperationWithCompletion:handler]; 

避免保留保留周期的常用方法是在定义块之前创build对象的弱引用,然后在块内创build一个强引用并将其设置为该弱引用。 这种方法经常用来避免强烈地捕捉块内的self

 - (void)someMethod { __weak MyType *weakSelf = self; [self someMethodWithABlockArg:^{ MyType *strongSelf = weakSelf; [strongSelf someOtherMethod]; }]; } 

块内创build的强引用可防止块在运行时释放对象。 当然,您可以对任何对象types执行相同的操作。

编辑2:看起来像[someBlock copy]确实很好。 你有没有试过在代码上运行分析? 当它被引用到块内时,可能是completion还没有初始化。