【发布时间】:2015-06-15 13:16:21
【问题描述】:
我正在我的项目中创建MKAnnotationView 的子类。它需要有两个属性来存储我需要在开始时在某处初始化的子视图。
MKAnnotationView 在其文档中列出了一个初始化程序 initWithAnnotation:reuseIdentifier:,所以我想我会简单地覆盖它:
class PulsatingDotMarker: MKAnnotationView {
let innerCircle: UIView
let outerCircle: UIView
override init!(annotation: MKAnnotation!, reuseIdentifier: String!) {
innerCircle = ...
outerCircle = ...
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
}
...
}
但这会导致运行时异常:
致命错误:对“PulsatingDotMarker”类使用未实现的初始化程序“init(frame:)”
好的,所以我猜initWithAnnotation:reuseIdentifier: 内部调用了initWithFrame:,所以它可能是我应该覆盖的那个。让我们试试吧:
class PulsatingDotMarker: MKAnnotationView {
let innerCircle: UIView
let outerCircle: UIView
override init(frame: CGRect) {
innerCircle = ...
outerCircle = ...
super.init(frame: frame)
}
...
}
然而,这会在创建注释视图对象时导致编译错误:
调用中的额外参数“reuseIdentifier”
嗯,所以如果我实现(必需的)初始化程序 initWithFrame:,它现在会丢失默认初始化程序 initWithAnnotation:reuseIdentifier:?
也许如果我添加一个只调用 super 的 initWithAnnotation:reuseIdentifier: 覆盖,它将再次可用,这会起作用吗?
class PulsatingDotMarker: MKAnnotationView {
let innerCircle: UIView
let outerCircle: UIView
init!(annotation: MKAnnotation!, reuseIdentifier: String!) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
}
override init(frame: CGRect) {
innerCircle = ...
outerCircle = ...
super.init(frame: frame)
}
...
}
不行,还是不好——编译错误:
属性 'self.innerCircle' 未在 super.init 调用中初始化
好的,如果我有一个initWithFrame:,但在initWithAnnotation:reuseIdentifier: 中初始化了子视图怎么办? (但是如果有人直接打电话给initWithFrame:呢?...)
class PulsatingDotMarker: MKAnnotationView {
let innerCircle: UIView
let outerCircle: UIView
init!(annotation: MKAnnotation!, reuseIdentifier: String!) {
innerCircle = ...
outerCircle = ...
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
...
}
毫不奇怪,Swift 告诉我:
属性 'self.innerCircle' 未在 super.init 调用中初始化
(这次是initWithFrame:)。
那我该怎么办?我不能在这里和那里都创建子视图,对吧?
class PulsatingDotMarker: MKAnnotationView {
let innerCircle: UIView
let outerCircle: UIView
init!(annotation: MKAnnotation!, reuseIdentifier: String!) {
innerCircle = ...
outerCircle = ...
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
}
override init(frame: CGRect) {
innerCircle = ...
outerCircle = ...
super.init(frame: frame)
}
...
}
又错了,这确实有效 - 即使我在同一个对象中分配了两次常量属性 (!)。
这应该如何正确完成?
(注意:该类还包括一个必需的 initWithCoder: 初始化程序,它仅调用第一个示例中的 fatalError,但该对象从未从情节提要中创建。)
【问题讨论】:
-
如果子视图被声明为
var innerCircle: UIView!怎么办?这可以避免“required init(xxx)”错误。 -
这正是我最终做的事情,但这听起来像是一个 hack - 将属性标记为可为空和可变,即使它应该是非空和常量只是为了取悦编译器......跨度>
-
我花了一些时间解决类似的问题,并做了一个测试项目,我认为我设法解决了原因(Objective C 类在其公共
init方法中调用[self initWith...]方法),但不幸的是,目前还没有解决方案 - stackoverflow.com/questions/31161143/…
标签: swift initialization mapkit mkannotationview initializer