5

我已经多次遇到这个问题,想知道正确的方法。

例如,假设我正在编写一个 iPhone 应用程序,并且我想要一个使用块的自定义警报视图类。

所以我写了这个类,然后在我的代码中我去:

MyAlertView *alert = [MyAlertView alertWithBlahBlahBlah...];
[alert addButton:@"button" withBlock:^{ ... }];
[alert show];

在警报视图类的某个地方,我们有

- (void)addButton:(NSString *)button withBlock:(void (^))block {
    [_blocks setObject:[block copy] forKey:button];
}

- (void)show {
    ... drawing stuff ...
    UIButton *button = ...
    [button addTarget:self selector:@selector(buttonPressed:) ...];
    ...
}

- (void)buttonPressed:(id)sender {
    ((void (^)())[_blocks objectForKey:[sender title]])();
}

因此,警报视图现在显示得很好。问题是,如果我点击一个按钮,它会尝试将buttonPressed:选择器发送到MyAlertView显示的对象。但是,此时MyAlertView已将其从超级视图中删除。ARC 决定,因为警报视图不再由任何人拥有,它应该被解除分配,不知道按钮将来需要向它发送消息。当点击按钮时,这会导致崩溃。

将警报视图保留在内存中的正确方法是什么?我可以使该MyAlertView对象成为使用它的类的属性,但这有点愚蠢(如果我想一次显示两个警报怎么办?)。

4

3 回答 3

7

如果一个对象保留在内存中,而您没有对它的引用,这称为内存泄漏。正如我在评论中所说,您需要保留对它的某种引用,以便 a)它不会被释放,b)您可以向它发送消息,并且 c)您可以在您的类被释放之前释放它。

最明显的方法是在你的类中使用一个属性。既然您说您不想这样做(也许您有很多),那么另一种可能的解决方案是保留您计划重用并最终解除分配的缓存对象数组。

于 2012-07-25T03:46:45.867 回答
1

很简单,你违反了内存管理规则。ARC 不会改变规则,它只是将它们自动化。如果你需要一个对象来维持生命,它需要有一个所有者。应用程序对象图中的每个对象,一直到应用程序委托,都有一个所有者。所有者是什么可能并不明显(有时所有者可能是一个自动释放池),但确实有一个。

如果您希望此视图持续存在,则它需要由某物拥有,即使它不是“当前正在使用”。如果它在屏幕上,它应该是视图层次结构的一部分。如果不是,理想的所有者很可能是创建它的对象。

于 2012-07-25T04:04:33.790 回答
1

我认为您可以使用performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay在运行循环中保留警报视图。

实际上,我刚刚遇到了使用此技能的 UIAlertView 的包装器实现。

检查UIAlertView 输入包装器以获取更多详细信息。

于 2012-07-25T03:52:16.793 回答