2016-04-14 14 views
1

我有一个关于使用回调块在给定的堆栈帧中释放控制器的一般问题。这目前正在按照要求工作,并且控制器正在获得一个dealloc消息并且没有其他明显的问题。这对于显示瞬态弹出窗口,对话框和其他视图(在主机类中不维护ivars或其他状态)很有用(在我看来)。如果控制器的xib设置为在关闭时释放,则会变得非常干净。我可以使用自己的回调块在方法中释放控制器吗?

这是一般模式:

- (void)showTransientView 
{ 
    MyCustomController *controller = nil; 

    void(^completeBlock)(ResponseCodeType) = ^(ResponseCodeType response){ 
     if (response == ResponseOk){ 
      [self transientViewDidEnd:controller]; 
     } 

     [controller autorelease]; //project is not using ARC 
    }; 

    controller = [[MyCustomController alloc] initWithCallback:completeBlock]; 
} 

我的问题是基本上都是有隐藏的问题或其他在这里的反对,我不考虑?

另外,除了明显移除[controller autorelease]之外,在打开ARC时该如何更改?

+2

,在将其他任何东西转换为ARC之前,你需要做的第一件事情就是要做。 – gnasher729

+1

@ gnasher729,它是一个非常大的(旧)代码库,我们正在研究这个代码库,但是希望在完成之前的几个地方使用这种模式。我想确保这个策略对ARC很友好,这就是为什么我这样构建第二个问题的原因。 –

+0

你说“这是_general_模式”。你可以验证'controller'是否实际上是一个局部变量?这对于转换为ARC的问题至关重要。 –

回答

1

不知道为什么你在这里做什么autorelease,因为它似乎是一个普通的release应该做的工作似乎你只是平衡alloc


随着ARC没有什么持有到该控制器所以这将是立即在此处释放。

你可以稍微调整一下,这样你就可以在实例化之后传递完成,这样块实际上会捕获实例,这是我相信你试图实现的。

您还需要添加__block存储符修改块内controllernil了控制器,以便将ARC如果你的项目没有使用ARC,那么很发送释放

__block MyCustomController *controller = MyCustomController.new; 

controller.completion = ^{ 
    controller = nil; 
}; 

// Using weak in this example to ensure the dispatch_after is not the thing holding onto our controller 
__weak __typeof(controller) weakController = controller; 
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
    weakController.completion(); 
}); 
+0

我认为,因为块被复制(现在真的存在于控制器实例中)并且堆栈中的原始信息已经消失,因为在控制器“结束”之前堆栈已经消失很久了。所以控制器现在在堆中浮动,所以回调基本上是自杀。在IIRC遇到访问问题之前,我尝试了这一点,但会再次尝试。无论如何'autorelease'是一个软性自杀的工作。 –

+1

通过这种设置,您本质上可以通过'MyCustomController'创建一个故意的保留周期。这就是运行完成处理程序的行为,这会导致保留周期被打破。如果你永远不运行完成处理程序并失去对你的控制器的引用,那么你将有一个很好的内存泄漏。 –

+0

这实际上是我正在做的非常好的升华。看起来这是一个折衷:潜在的内存泄漏(取决于应用程序)或为应用程序的这部分中的每个潜在弹出窗口和模式存储@property。警惕我猜。 –

相关问题