Kub*_*der 11 initialization initializer mapkit mkannotationview swift
我正在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)
}
...
}
Run Code Online (Sandbox Code Playgroud)
但这会导致运行时异常:
致命错误:对'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)
}
...
}
Run Code Online (Sandbox Code Playgroud)
但是,这会在创建注释视图对象时导致编译错误:
调用中的额外参数'reuseIdentifier'
嗯,所以如果我实现(必需的)初始化器initWithFrame:,它现在会丢失默认的初始化器initWithAnnotation:reuseIdentifier:?
也许如果我添加一个覆盖initWithAnnotation:reuseIdentifier:,只是调用super它将再次可用,这会工作吗?
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)
}
...
}
Run Code Online (Sandbox Code Playgroud)
不,还是不好 - 编译错误:
属性'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)
}
...
}
Run Code Online (Sandbox Code Playgroud)
毫不奇怪,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)
}
...
}
Run Code Online (Sandbox Code Playgroud)
错了,这实际上有效 - 即使我在同一个对象(!)中分配两次常量属性.
该如何正确完成?
(注意:该类还包括一个必需的initWithCoder:初始化程序,它只是fatalError从第一个示例调用,但该对象永远不会从故事板创建.)
不幸的是,MKAnnotationView您要实施的强制措施init(frame: CGRect)意味着您必须初始化该方法中的所有实例变量.
本文将对此进行更多解释
对于只能使用传入值初始化的变量,您必须使这些变量可选,并将它们设置为nil init(frame: CGRect).
原因是我怀疑MKAnnotationView正在调用self.initWithFrame: rect其Objective-C init方法.这样,如果子类重写initWithFrame:(CGRect) rect它将被调用.但是,这会导致swift问题,因为如果声明自定义指定的初始化程序,则不会继承超类的初始化程序.因此,您必须init(frame: CGRect)在子类中实现它.
我遇到了同样的问题UITableVeiwController.它的标题看起来遵循相同的模式.即两个可归属的指定初始化程序.
这让我非常伤心.但你能做什么呢.
对于我的应用程序,我选择的解决方案是将子视图声明为可选并在 initFrame 中实例化它...
var innerCircle: UIView?
这是我的代码...
class EventAnnotationView: MKPinAnnotationView
{
static var REUSE_ID = "EventAnnotationView"
var imageView: UIImageView?
override init(frame: CGRect)
{
super.init(frame: frame)
// Create subview for custom images
imageView = UIImageView(frame: CGRectMake(0, 0, 22, 22))
...
}
override init(annotation: MKAnnotation!, reuseIdentifier: String!)
{
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
}
required init(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
}
}
Run Code Online (Sandbox Code Playgroud)
感觉不像黑客:),但需要更多代码/工作,因为子视图是可选的。
希望这可以帮助。