【问题标题】:IBAction not getting called from Subviews button click未从子视图按钮单击调用 IBAction
【发布时间】:2016-10-23 17:12:47
【问题描述】:

所以我整个晚上都在试图解决我的问题,即单击 UIViewController 中的按钮不会触发 IBAction。

我的情况

我正在使用情节提要构建我的应用程序,而我的主 ViewController 是 TabBarViewController。所说的 TabBarViewController 的其中一项是,我们称之为MainViewController

MainViewController 后面是BackgroundViewController,它只包含相机预览,没有其他内容。

BackgroundViewController 被添加到MainViewController 中,如下所示:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
BackgrondViewController *bckgController = (BackgrondViewController *)[storyboard instantiateViewControllerWithIdentifier:@"background"];

[self.view addSubview:bckgController.view];
[self.view sendSubviewToBack:bckgController.view];

到目前为止一切正常,我之所以提到它,是因为这可能是相关的。

TopController

现在我想将另一个 ViewController 添加到 MainViewController,这次在顶部。我们将顶视图控制器称为TopViewController

所以首先我将它设置为这样:

TopViewController *topController = (TopViewController *)[storyboard instantiateViewControllerWithIdentifier:@"top"];
topController.view.backgroundColor = [UIColor clearColor];

我添加了 clearColor 是因为在我的应用中需要它,并且它确认这不会改变任何东西(相信我,我试过了)。

好的,现在我添加新创建的视图如下(我们仍在MainViewController 内)

 [self.view addSubview:topController.view];
 [self.view bringSubviewToFront:topController.view];

实际上它确实显示透明视图,中间只有一个按钮。

问题

无论我尝试什么,我都无法让按钮调用它的 IBAction 方法。

已知事实和我的尝试

  • TopViewController 实际上在 MainViewController 视图之上,我通过获取 MainViewController 的所有子视图来检查这一点,获取最后一个元素并将其与 TopViewController 的视图进行比较。
  • IBAction 已正确链接到我需要单击的按钮(通过情节提要和鼠标悬停方法插座确认)
  • TopViewController 添加到 TabBar 效果很好,Button 完成了它的工作
  • Button 是可视觉点击的,点击时会执行默认动画
  • 设置topController.view.userInteractionEnabled = YES 不起作用
  • TopViewController 上添加单击处理程序并单击屏幕上的任何位置不起作用,但将其添加到MainViewController 确实有效(尽管TopViewController 位于顶部,但单击屏幕上的任何位置都会触发定义的操作)
  • 所有尺寸、ID 和相应的类别都经过验证
  • viewDidLoadTopViewController 被调用

请帮助我摆脱困境。谢谢!

【问题讨论】:

  • 我不会回答你的问题,但我想让你知道,像你一样放置 ViewController 的视图并显示为子视图不是一个好习惯。相反,你应该使用 containerViewController 或制作BackgroundViewController 是 UIView 的子类,而不是 UIViewController(我认为您的情况适合这里)。希望对你有帮助。
  • @FormigaNinja 感谢您的输入,不幸的是,我用于 BackgroundViewController 的 SDK 迫使我将 UIViewController 显示为子视图。然而,顶视图控制器每个用户只显示一次几秒钟,所以没什么大不了的

标签: ios objective-c uiviewcontroller hierarchy


【解决方案1】:

您是否通过使用实例变量或属性来保留topController

一个简单的方法是在 MainViewController.h 文件中创建一个属性。

@interface MainViewController : UIViewController
    @property (nonatomic, strong) TopViewController *topViewController;
@end

或在 MainViewController.m 文件的顶部

@interface MainViewController ()
    @property (nonatomic, strong) TopViewController *topViewController;
@end

然后在创建后随时设置属性。

self.topViewController = topController;

说明

-[UIView addSubview:] 保留视图,但不保留视图控制器。如果不保留视图控制器,那么 ARC 将在函数结束时释放视图控制器。您可以通过覆盖-[TopViewController dealloc] 来验证这一点。当您按下按钮时,它会尝试向 now nil 视图控制器发送消息。

【讨论】:

  • 我知道这是怎么回事,我来自 android 开发,不太明白如何通过保留视图控制器来解决这个问题,你能详细说明一下吗?
  • 哦!基本上,您将在 MainViewController 类中创建一个实例变量,然后将 topController 分配给它,基本上使其成为类成员。我用最简单的方法更新了我的答案。
  • 谢谢,确实有效!但是,将强大的 viewcontroller 属性设置为另一个视图控制器是一种好习惯吗?
  • 只要是单向关系就可以。 UITabBarController 和 UINavigationController 实际上都强烈保留了它们的视图控制器。这确保了子视图控制器不会在父视图控制器仍然存在并依赖于它们时被销毁。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多