从完成块中保护我的代码免受僵尸的攻击

ban*_*isa 5 objective-c grand-central-dispatch ios objective-c-blocks

我熟悉委托模式和nilling我的委托,特别是在我的视图控制器消失时仍在进行的异步调用时.我没有委托,并且回调成功返回nil对象.

我现在正在尝试使用完成块来使我的代码更容易阅读.

我从视图控制器调用网络服务,并传递一个更新我的UITableView的块.在正常情况下它工作正常.但是,如果我在视图完成之前离开视图,则执行完成处理程序块 - 但是UITableView现在是一个僵尸.

什么是处理这个的通常模式?

更新代码示例

这是一个iPad应用程序,我在屏幕上同时有两个视图控制器,就像拆分视图一样.一个是细节,另一个是图像网格.我点击一个图像,它告诉细节加载信息.但是,如果我在他们有机会进行网络通话之前点击图像太快 - 我有问题.在更改图像时,会调用下面的代码来计算图像的最爱....

所以这就是我的困境,如果我使用下面的代码 - 它工作正常,但如果你在网络响应之前切换图像,它会在仪器中泄漏.

如果我删除__block并传入self,那么它会与僵尸一起崩溃.

我无法获胜......我确信我错过了使用积木的基本原则.

__block UITableView *theTable = [self.table retain];
__block IndexedDictionary *tableData = [self.descriptionKeyValues retain];
FavouritesController *favourites = [Container controllerWithClass:FavouritesController.class];
[favourites countFavouritesForPhoto:self.photo 
                         completion:^(int favesCount) {

                             [tableData insertObject:[NSString stringWithFormat:@"%i", favesCount]   
                                              forKey:@"Favourites:" atIndex:1];                 
                             [theTable reloadData];

                             [tableData release];
                             [theTable release];
                         }];
Run Code Online (Sandbox Code Playgroud)

有小费吗?谢谢

第二次更新

我改变了加载收藏夹的方式.我不是将收藏夹作为单身人物,而是在每次照片更改时创建一个实例.通过替换它并杀死旧的 - 块无处回调(我猜它甚至不存在),我的代码现在看起来像下面的,它似乎工作:

[self.favourites countFavouritesForPhoto:self.photo 
                         completion:^(int favesCount) {      
                             [self.descriptionKeyValues insertObject:[NSString stringWithFormat:@"%i", favesCount]   
                                              forKey:@"Favourites:" atIndex:1];                 
                             [self.table reloadData];
                         }];
Run Code Online (Sandbox Code Playgroud)

它不会泄漏,也不会崩溃.

bne*_*ely 0

我建议您测试表视图在块的开头不为零。听起来当 tableview 的父视图离开屏幕时,它会被正确丢弃,因此在那之后,所有 tableview 操作都无效。

将 UITableView 保留在块内是一个坏主意,因为数据源/表视图更新可能会导致隐式方法调用和通知,如果表视图不在屏幕上,则这些通知和通知将不相关。