0

我有ParentViewControllerallocates ChildViewController,将其推送到控制器堆栈并释放它。

ChildViewControllerProductDownloadDelegateProtocol实现Product 类所需的协议。

在某个时候,ChildViewController创建一个 Product 对象并将其自身设置为其downloadDelegate.

下载时,ProductChildViewController通过ProductDownloadDelegateProtocol.

如果用户在下载时按下导航栏中的后退按钮,ChildViewController则下载百分比的下一次更新Product会导致EXC_BAD_ACCESS.

虽然Product检查 if downloadDelegateis nil,但问题仍然存在,因为ChildViewController/downloadDelegate已释放,但未设置为nil。我不知道哪个点最好设置ChildViewControllernil.

我的设计错了吗?

4

2 回答 2

3

如果您ChildViewController创建了一个实例Product并将自己设置为委托,那么当它即将被卸载时,它应该有责任将自己作为委托移除。无论是在它的viewDidUnload还是dealloc方法中,您都应该将Product委托设置为 nil。

如果ChildViewController保留(假设您正在重用视图控制器),也许您可​​以将其作为viewWillDissappear方法中的委托删除。

解决此特定 EXC_BAD_ACCESS 问题的另一个解决方案是移至 ARC 并使用归零弱引用(请参阅此处的好文章,http://www.mikeash.com/pyblog/friday-qa-2010-07-16-zeroing-weak -references-in-objective-c.html)。

尽管如此,我还是建议您出于正确的原因迁移到 ARC,而不是解决您面临的这个特定问题。

于 2012-07-20T18:56:33.293 回答
1

我的经验法则是这样的:你永远不应该成为你不拥有的对象的代表。在这里,“自己”的意思是“强烈引用”(在 ARC 术语中)。主要的例外是当委托保留你时, UIApplication.delegate 因为这有点奇怪。

通常我将逻辑捆绑到设置器中,如下所示:

-(void)setProduct:(Product*)p
{
  product.delegate = nil;
  [product release];
  product = [p retain];
  product.delegate = self;
}

-(void)dealloc
{
  self.product = nil;
}

但是,这种设计的一个潜在问题是“产品下载”只能有一个代表。如果你离开它ChildViewController然后回到它的(一个新实例)怎么办?它们是不同的Product实例,都被下载了吗?

更好的方法可能是拥有一个下载管理器单例(尽管我讨厌单例)来管理下载并使用 NSNotification/NSNotificationCenter 进行进度通知。

于 2012-07-20T19:15:11.233 回答