Bil*_*ill 11 objective-c initializer designated-initializer swift
我正在尝试创建一个简单的UIBarButtonItem的Swift子类:
class LabelBarButtonItem: UIBarButtonItem {
let label: UILabel
init(text: String) {
self.label = UILabel(frame: CGRectZero)
self.label.tintColor = UIColor.grayColor()
super.init(customView: self.label)
self.label.text = text
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试实例化这个:
let countButton = LabelBarButtonItem(text: "0 items")
Run Code Online (Sandbox Code Playgroud)
代码编译正确但在运行时失败:
fatal error: use of unimplemented initializer 'init()' for class 'TestProject.LabelBarButtonItem'
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么在这种情况下会发生这种情况,或者一般来说是什么原则导致这个问题.在init(text)初始化应直接委托给init(customView)超类.为什么要init()打电话?它不应该涉及.
任何人都可以解释发生了什么吗?当我试图继承其他UIKit类时,会出现类似的问题
mat*_*att 11
问题是init(customView:)电话init().
由于你有一个必需的初始化程序,你不再继承init().因此,你必须实现它,即使只是为了调用super.init().
然后,您面临不得不在初始化所有属性(轻度)的烦恼init(),以及在init(text:).但是,在您的特定情况下,首先不需要在初始化程序中执行此操作.我会像这样写你的课:
class LabelBarButtonItem: UIBarButtonItem {
let label = UILabel(frame: CGRectZero)
init(text: String) {
super.init(customView: self.label)
self.label.text = text
self.label.tintColor = UIColor.grayColor()
}
private override init() {
super.init()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Run Code Online (Sandbox Code Playgroud)
在你的评论中,你问:
但是现在如果我覆盖init(),我的类的客户端可以通过调用LabelBarButtonItem()来创建LabelBarButtonItem的无效实例
正确.这就是我将init()覆盖标记为的原因private.请注意,仅当此类在文件中单独关闭时,此方法才有效.
另一种可能性是将所有初始化程序(包括init(coder:))标记为convenience.现在你继承init()了,整个问题就消失了.然而,这引入了另一组问题,并留给读者练习.
为了澄清,我认为整个情况都是Swift中的一个错误.在最近的一次修订(Xcode 6.1?)之前,它没有像IIRC这样的行为.您正在被这样的事实所约束super.init(customView:)调用你的 init().你可以说这是错的; 你有一个错误报告的好用例.运行时崩溃似乎也是错误的行为; 如果发生这种情况,为什么编译器不会阻止我们呢?也许其他人可以证明Swift在这种情况下做了什么.我只想解释一下.
编辑此答案来自2014年,旨在解决当时存在的错误.在现代iOS版本中,bug已经消失,您可以这样说:
class LabelBarButtonItem: UIBarButtonItem {
init(text: String) {
let label = UILabel(frame: .zero)
label.text = text
label.sizeToFit()
super.init()
self.customView = label
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Run Code Online (Sandbox Code Playgroud)
或者你可以这样说:
class LabelBarButtonItem: UIBarButtonItem {
convenience init(text: String) {
let label = UILabel(frame: .zero)
label.text = text
label.sizeToFit()
self.init(customView: label)
}
}
Run Code Online (Sandbox Code Playgroud)
在最初提出这个问题的时刻,这些都不可能.
我不得不为一个项目继承 UIBarButtonItem 并且按照 Matt 的回答已经绰绰有余,只有一点区别。我必须为初始化程序添加便利才能使代码正常工作。就我而言,我的子类中没有属性。
这是适用于 Swift 3 的代码,以防它对任何人有帮助。
class PlayerBarButtonItem: UIBarButtonItem {
convenience init(assetName: String, target: Any, selector: Selector) {
let barButton = UIButton(frame: CGRect(x: 0, y: 0, width: 34, height: 34))
let barButtonImage = UIImage(named: assetName)?.withRenderingMode(.alwaysTemplate)
barButton.setImage(barButtonImage, for: .normal)
barButton.tintColor = UIColor.white
barButton.addTarget(target, action: selector, for: .touchUpInside)
self.init(customView: barButton)
}
private override init() {
super.init()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2730 次 |
| 最近记录: |