iOS 9.0 以下的分段控件 addTarget() 崩溃应用

Posted

技术标签:

【中文标题】iOS 9.0 以下的分段控件 addTarget() 崩溃应用【英文标题】:Segmented control addTarget() crashing app below iOS 9.0 【发布时间】:2017-02-05 13:23:18 【问题描述】:

我的应用最近发布了,但它支持 ios 8.2。

不幸的是,在 iOS 9.0 以下,点击一个以编程方式添加的分段控件会使应用程序崩溃,而控制台中没有错误消息。

我认为添加目标的行可能会导致问题:

下面这行放在我的自定义单元格的 init() 里面,分段控件是一个实例 var 并在其父视图控制器中调用一个方法

segmentedControl.addTarget(ListViewController(), action: #selector(ListViewController.segmentedControlToggled(segmentedControl:)), for: .valueChanged)

同样,这在 iOS 9.0 中可以正常工作。

设置工作正常,只有在点击分段控件时才会崩溃。

选择器应该有另一种语法吗?

感谢您的任何建议!

【问题讨论】:

【参考方案1】:

根据addTarget的文档:

控件不保留目标参数中的对象。当目标对象附加到控件时,您有责任保持对目标对象的强引用。

这意味着您需要将target 参数的值存储在某处,而您无法实现:

segmentedControl.addTarget(ListViewController(),...)

ListViewController 将在没有其他引用时立即被释放,这里要记住的重要一点是,你无法提前知道释放何时发生,因为你不知道如何可能其他对象会引用您的对象。

为确保目标不会被释放,请将 ListViewController 实例存储到属性中。

崩溃并非特定于 iOS 版本,可能是在某些 iOS 版本上,ListViewController 会更快地被释放。

【讨论】:

非常感谢,Cristik,我忽略了这一点。我改变了它,它解决了这个问题!但是,我仍然不明白为什么这在 8.4 以上的每个版本中都有效,但在以下版本中无效。 @nontomatic 目标可能被其他间接保持其存活的对象捕获(保留)。而 iOS 8.3 及更低版本没有这些对象。基本上,由于 UIKit 的一些实现细节,您的应用程序在 8.4 及更高版本中运行良好,但是由于这些超出您的控制范围,您最好为自己保留一个强有力的参考。 感谢您的跟进,确实有道理,谢谢!

以上是关于iOS 9.0 以下的分段控件 addTarget() 崩溃应用的主要内容,如果未能解决你的问题,请参考以下文章

iOS系列 基础篇 09 开关滑块和分段控件

RadioGroup实现类似ios的分段选择(UISegmentedControl)控件

在不更改界面的情况下更新ios中的分段控件

UINavigationBar中的分段控件奇怪的截图iOS

iOS在导航栏上居中显示分段控件(UISegmentedControl)

《iOS Human Interface Guidelines》——Segmented Control