IOS 9 - 子视图上的 UIButton 不触发 IBAction 插座

IOS 9 - UIButton on subview does not fire IBAction outlet

我已经为此苦苦挣扎了几天,但一直无法查明问题的原因,正如标题所说,子视图上的 UIButton 没有触发"clicked" 时的 IBAction 出口。

让我详细说明一下,我正在开发一个 "tinder-like" 应用程序,我正在使用 this third party library。我正在实现自定义视图,其中包含按钮和其他控制器。这些 "Cards" 中的按钮未触发其 IBAction 插座。

据我所知,该库执行以下操作:

堆叠 3 "DraggableViews" 彼此叠加,每个可拖动视图有 2 个 child 视图,一个是内容视图,我的自定义视图所在的位置,另一个是叠加视图,上面有一个图像视图。可拖动视图使用两个手势识别器来完成它的工作,第一个是点击手势,它调用委托方法来处理卡片中的点击事件(在他们的示例中,它用于显示浏览器视图)。第二个手势是用于实现卡片滑动功能的平移手势。

我已完成作业并尝试了几种不同的解决方案,但我无法触发 IBAction。我尝试了以下方法:

我还在故事板中检查了自定义视图中的所有相关视图和控制器都启用了 userInteractionEnabled 选项。

我不知道它是否相关,但我的自定义视图位于 xib 文件中,当我将视图传递给库时,我通过实例化视图控制器并传递它的视图来实现,如下所示:

if let vc = spiViewConntroller {
        return vc.view
    }

如有任何帮助或建议,我们将不胜感激!

干杯!

编辑: 继续寻找真相,我已经从库中完全删除了覆盖视图,在 UI 调试器上检查我的自定义视图,我可以看到覆盖视图及其 ImageView 不再存在。该按钮仍然没有触发其出口,因此我可以假设叠加视图不会导致此问题。

我 fork 了 Koloda 库并创建了一个 demo example 的分支,分支名称是 "WhosebugDemo"。我添加了一个带有一个按钮的自定义视图,我在它的视图控制器中创建了两个插座,我在其中更改按钮的标题(有效),视图确实加载了。我还禁用了按钮上的两个手势以复制我当前在我的应用程序中获得的内容。 如果你要复制它,你需要刷掉第一张卡片,因为索引 0 处的卡片不会禁用手势。

我会继续挖掘,希望有人能指出我做错了什么!

干杯。

我可以建议一种方法,它可以帮助您检测问题。当模拟器为 运行 时,使用 xcode 中的调试器视图。它将以 3-D 模式向您显示视图的层次结构,这可以帮助您找出问题所在。 如何使用 debuggin 视图: https://developer.apple.com/library/ios/documentation/ToolsLanguages/Conceptual/Xcode_Overview/ExaminingtheViewHierarchy.html

好的,我找到了答案。在进一步挖掘之后,我能够解决这个问题。但是我的解决方案感觉很脏,我不确定它是否破坏了 MVC 模式。

我认为我的问题是我的 xib 文件的自定义视图控制器以某种方式丢失或无法响应这些事件。在创建要显示为可拖动卡片内容的视图时,我正在创建视图控制器的实例并返回其视图。令我感到奇怪的是,视图控制器的 ViewDidLoad 方法在加载视图时正在执行其工作(即更改插座的值)。

解法: 我从 lib 中删除了文件所有者,创建了一个继承自 UIView 的自定义 class,例如 MyCustomUIView,并将视图控制器逻辑、其出口和操作移动到 class.然后在 xib 文件上,我将内容视图链接到 MyCustomUIView。然而,这个解决方案感觉很脏,因为我希望视图的视图控制器能够处理所有逻辑。可能需要多读一些关于 nib 和可重用视图的文章。

丹尼尔。 您的问题是您没有将视图控制器添加为子视图控制器以使用 Koloda 操作的视图控制器。结果显示了你的 vc.view,因为 Koloda 保留了它,但没有人保留你的视图控制器,所以你失去了重要的生命周期方法,它被释放了。

您尝试使用的方法称为容器视图控制器。 Apple 在此处对其实施提出了建议:https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html

此处简单实现:

- (void) displayContentController: (UIViewController*) content {
   [self addChildViewController:content];
   content.view.frame = [self frameForContentController];
   [self.view addSubview:self.currentClientView];
   [content didMoveToParentViewController:self];
}