我正在尝试在 Objective-C 中实现委托模式,但是有时在调用委托时遇到错误访问异常。这似乎是由被释放的代表引起的。Apple 不建议保留代表。
在尝试向其发送消息之前,如何检查我的代表是否仍然有效?
我正在尝试在 Objective-C 中实现委托模式,但是有时在调用委托时遇到错误访问异常。这似乎是由被释放的代表引起的。Apple 不建议保留代表。
在尝试向其发送消息之前,如何检查我的代表是否仍然有效?
如果委托有可能被 setter 释放,那么您的设计就有问题。您应该只在生命周期比委托本身短的对象上设置委托。例如,在子视图/控制器上设置委托很好,因为子视图/控制器的寿命比调用者短。
AFAIK,没有可靠的方法来检测对象是否已经被释放。
Apple 关于不保留代表的意思是对象不应该保留它们的代表,因为它们不拥有它们。这些只是处理消息的对象。
这并不意味着您根本不应该保留代表。创建委托的对象需要拥有它。在非 GC 应用程序的上下文中,这意味着它应该处理保留和释放周期,而对于 GC 应用程序,这意味着控制器对象在 iVar 中保留指向委托的指针。
没有看到一些代码或错误消息,很难找到这个问题的根源。
在 photoviewer 应用程序中,我使用异步 http 来加载图像;碰巧用户经常在 http 下载完成之前关闭当前视图(由我的异步 http 对象通过委托引用),从而在调用视图控制器委托方法时导致 BAD_ACCESS。我通过在视图控制器的 dealloc 块中将 .delegate 设置为 nil 解决了这个问题
我也想分享我的经验,这与 Nico 的经验非常相似。
我一直在使用 LazyTablesCode 的修改示例,这是一个直接来自 Apple 并异步加载 UITableView 中的图像的示例。下载器和它通过委托创建的视图之间的通信。
在我的代码中,我遇到的问题是,当应该通过委托调用的表单已被释放时,图像的加载有时会完成。我被迫在 viewController 的代码中添加了这段代码(dealloc 方法):
if (self.nsDictionaryWithObjectsDownloading != nil) {
for (id theKey in self.nsDictionaryWithObjectsDownloading) {
Myobj *downloader = [self.nsDictionaryWithObjectsDownloading objectForKey:theKey];
downloader.delegate = nil;
}
}
似乎这些行正在解决问题。无论如何,在执行 downloader.delegate = nil; 时,如果它是一个好的解决方案,甚至是关于内存问题,将非常感谢您的意见。
谢谢和问候,