我编写了一个UIStackView子类,但是我遇到了一个奇怪的运行时问题。下面是一些可以看到的示例代码:
class SubclassedStackView: UIStackView {
init(text: String, subtext: String) {
let textlabel = UILabel()
let subtextLabel = UILabel()
textlabel.text = text
subtextLabel.text = subtext
super.init(arrangedSubviews: [textlabel, subtextLabel])
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}如果您然后使用它,如下所示:
let stackView = SubclassedStackView(text: "Test", subtext: "Uh-oh!")您将得到具有以下消息的运行时异常:
致命错误:类'test.SubclassedStackView‘使用未实现的初始化器’init(框架:)‘
查看一下调用堆栈就会发现,基初始化器-[UIStackView initWithArrangedSubviews:]试图调用子类上的init(frame: CGRect),这是有意留下的未实现的。
当然,我可以实现这个额外的初始化器,就像超类调用它一样奇怪,但在现实生活中,这将迫使我更改属性以使用可选类型(或隐式展开选项),而不必这样做。
我也可以调用init(frame:)而不是init(arrangedSubviews:),然后调用addArrangedSubview(view:)来添加已安排的子视图。运行时问题将消失,但我不想提供一个框架。
为什么超类的初始化程序调用子类的初始化程序?有人能提出解决这一问题的方法而不引入选项吗?
编辑:苹果承认了这个错误,应该在iOS 10中修复。http://www.openradar.me/radar?id=4989179939258368仍然适用于iOS 8-9。
发布于 2016-04-08 15:14:31
我不确定这是否能满足您的需要,但我设法通过在UIStackView上进行扩展来解决这个问题
extension UIStackView {
convenience init(text: String, subtext: String) {
let textlabel = UILabel()
let subtextLabel = UILabel()
textlabel.text = text
subtextLabel.text = subtext
self.init(arrangedSubviews: [textlabel, subtextLabel])
}
}
// ...
let sv = UIStackView(text: "", subtext: "") // <UIStackView: 0x7fcd32022c20; frame = (0 0; 0 0); layer = <CATransformLayer: 0x7fcd32030810>>发布于 2016-04-08 15:21:15
查看一下调用堆栈就会发现,基初始化器-UIStackView initWithArrangedSubviews:正在试图调用子类上的init(frame: CGRect),该子类是故意留下未实现的。
为什么不直接添加缺少的构造函数呢?
override init(frame: CGRect) {
super.init(frame: frame)
}由于您已经提供了您自己的框架初始化器,所以问题来自于无法使用的框架初始化器,它需要它的内部实现。如果框架无论如何都将由AutoLayout管理,那么您不需要关心最初设置的是什么,所以您可以让它执行使用子视图初始化所需的内部例程。从上面的代码中我看不出你为什么需要添加选项。
发布于 2018-02-03 15:24:32
init(arrangedSubviews: []是一个方便的初始化器。根据文档,您必须调用超类的指定初始化器(即init(frame:))
https://stackoverflow.com/questions/36502790
复制相似问题