首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Swift编写的UIStackView子类可能由于未实现init而崩溃(框架:)

用Swift编写的UIStackView子类可能由于未实现init而崩溃(框架:)
EN

Stack Overflow用户
提问于 2016-04-08 14:53:48
回答 3查看 4.3K关注 0票数 3

我编写了一个UIStackView子类,但是我遇到了一个奇怪的运行时问题。下面是一些可以看到的示例代码:

代码语言:javascript
复制
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")
    }
}

如果您然后使用它,如下所示:

代码语言:javascript
复制
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。

EN

回答 3

Stack Overflow用户

发布于 2016-04-08 15:14:31

我不确定这是否能满足您的需要,但我设法通过在UIStackView上进行扩展来解决这个问题

代码语言:javascript
复制
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>>
票数 3
EN

Stack Overflow用户

发布于 2016-04-08 15:21:15

查看一下调用堆栈就会发现,基初始化器-UIStackView initWithArrangedSubviews:正在试图调用子类上的init(frame: CGRect),该子类是故意留下未实现的。

为什么不直接添加缺少的构造函数呢?

代码语言:javascript
复制
override init(frame: CGRect) {
    super.init(frame: frame)
}

由于您已经提供了您自己的框架初始化器,所以问题来自于无法使用的框架初始化器,它需要它的内部实现。如果框架无论如何都将由AutoLayout管理,那么您不需要关心最初设置的是什么,所以您可以让它执行使用子视图初始化所需的内部例程。从上面的代码中我看不出你为什么需要添加选项。

票数 2
EN

Stack Overflow用户

发布于 2018-02-03 15:24:32

init(arrangedSubviews: []是一个方便的初始化器。根据文档,您必须调用超类的指定初始化器(即init(frame:))

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36502790

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档