0

我有一个 B UIViewController,里面有关闭按钮。

        -(IBAction) close:(id) sender 

从 A viewcontroller 我呈现 B viewcontroller 像这样

  [self presentViewController:B animated:YES completion:NULL];

然后一切正常,我可以点击 B 里面的关闭按钮。

但是,如果我这样做

   B* bcontrol=[[B alloc] init];
   [self.view addsubview bcontrol.view];

那么这样,如果我点击关闭按钮,它会产生 EXEC_BAD_ACCESS 错误。

这是为什么?有任何想法吗?

4

2 回答 2

1

我假设您正在使用ARC。

您将 bcontrol 创建为局部变量并且不保留对它的引用,因此当您剥离其视图时,ARC 会释放它。然后你的按钮尝试在一个释放的对象中触发一个动作……你知道其余的。

使 B 成为一个强大的属性,以便在您需要它的视图时它会一直存在。

于 2012-07-03T01:24:11.060 回答
0

您没有为您的close方法提供代码。close方法代码必须更改以对应您转换到此新视图的方式。如果您必须通过查看控制器 B,presentViewController那么您可能会通过以下方式返回 A:

- (IBAction)close:(id)sender
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

然后,您考虑是否通过

B* bcontrol=[[B alloc] init];
[self.view addsubview bcontrol.view];

显然,这dismissViewControllerAnimated将不再起作用。所以问题是您将close方法更改为什么。

但在我开始之前,这种结构存在两个问题。首先,如果你在非 ARC 项目中这样做,你会泄露你的控制器。更糟糕的是,如果您使用 ARC 执行此操作,您将收到异常,因为控制器将在超出范围时被释放(如果您打开僵尸,您将看到有意义的错误)。这个问题的典型答案是制作B* bcontrolA 的和 ivar,或者做这样的事情,这样指针就bcontrol不会被释放到你身上。这解决了眼前的问题。

其次,更大的问题是整个构造(将控制器的视图添加为另一个视图的子视图)通常不是一个好主意,因为您的视图控制器层次结构和视图层次结构不同步。(有关这些问题的详细讨论,请观看关于 View Controller Containment 的 WWDC 2011 session 102。)您可能不会收到轮换事件。你不知道还会发生什么(因为 iOS 假设它可以导航视图控制器层次结构以便将消息发送到各种控制器)。最重要的是,获取另一个视图控制器的视图并将其添加为当前视图的子视图并不是一个好主意。你这样做的唯一一次是如果你正在做真正的视图控制器包含并且已经完成addChildViewController并且didMoveToParentViewController并且您只想获得第一个视图(请参阅上述视频)。

但是,如果你决心做这个[self.view addSubview:bcontrol.view];构造,那么显然你不能dismissViewControllerAnimated在你 B 的close方法中使用它。从 A 的视图中删除 B 的视图的合乎逻辑的方法是[self.view removeFromSuperView];. 但是接下来您面临的挑战是如何确保您的 A 类现在清理您最初创建的 B 实例,否则您将有泄漏。

归根结底,这不是一个好主意。坚持使用presentViewController(你会用 解雇dismissViewControllerAnimated)或pushViewController(你会用 解雇popViewControllerAnimated)或使用视图控制器包含。鉴于您讨论了“关闭”按钮的概念,这意味着一个真正适用于presentViewControllerpushViewController模型的 UI。

于 2012-07-03T01:29:14.743 回答