Tworzę podklasę MKAnnotationView
w moim projekcie. Musi mieć dwie właściwości do przechowywania subskrybentów, które muszę zainicjować gdzieś na początku.jakie inicjatory powinna mieć podklasa MKAnnotationView w Swift?
MKAnnotationView
ma jeden inicjator wymienione w dokumentacji, initWithAnnotation:reuseIdentifier:
, więc pomyślałem, że po prostu zastąpić że:
class PulsatingDotMarker: MKAnnotationView {
let innerCircle: UIView
let outerCircle: UIView
override init!(annotation: MKAnnotation!, reuseIdentifier: String!) {
innerCircle = ...
outerCircle = ...
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
}
...
}
Ale to powoduje wyjątek środowiska wykonawczego:
fatal error: use of unimplemented initializer 'init(frame:)' for class 'PulsatingDotMarker'
Ok, więc ja domyślam się initWithAnnotation:reuseIdentifier:
wewnętrznie dzwoni initWithFrame:
, więc prawdopodobnie to powinienem zastąpić. Spróbujmy że:
class PulsatingDotMarker: MKAnnotationView {
let innerCircle: UIView
let outerCircle: UIView
override init(frame: CGRect) {
innerCircle = ...
outerCircle = ...
super.init(frame: frame)
}
...
}
To jednak powoduje błąd kompilacji podczas tworzenia obiektu widoku adnotacji:
Extra argument 'reuseIdentifier' in call
Hmm, więc jeśli wdrożenie (wymagane) inicjator initWithFrame:
, to teraz traci domyślny inicjatora initWithAnnotation:reuseIdentifier:
?
Może po dodaniu przesłonięcia initWithAnnotation:reuseIdentifier:
, które po prostu zadzwoni super
, będzie ponownie dostępne, czy to zadziała?
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)
}
...
}
Nie, nadal nie jest dobra - błąd kompilacji:
Property 'self.innerCircle' not initialized at super.init call
Ok, gdybym miał initWithFrame:
, ale zainicjowaniu subviews w initWithAnnotation:reuseIdentifier:
? (? Ale co jeśli ktoś po prostu wywołuje initWithFrame:
bezpośrednio ...)
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)
}
...
}
Nic dziwnego, że Swift chroni mnie od tego, mówiąc mi:
Property 'self.innerCircle' not initialized at super.init call
(tym razem w initWithFrame:
).
Co powinienem zrobić? Nie mogę utworzyć subviews zarówno tutaj, jak i tam, prawda?
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)
}
...
}
Źle ponownie, to rzeczywiście działa - choć jestem przypisywania stałą właściwość dwa razy w tym samym obiekcie (!).
Czy ktoś ma pomysł, jak to zrobić prawidłowo?
(Uwaga: klasa obejmowała również wymagane initWithCoder:
inicjator że po prostu wywołuje fatalError
z pierwszego przykładu, ale obiekt nie jest tworzony z serii ujęć.)
Co jeśli subviews są zadeklarowane jako 'var innerCircle: UIView!'? Może to uniknąć błędów "wymaganych init (xxx)". – Anna
Dokładnie to zrobiłem, ale brzmi to jak włamanie - oznaczanie właściwości jako zerowalnej i zmienne, nawet jeśli powinno być niezerowe i stałe, żeby zadowolić kompilator ... –
Spędziłem trochę czasu na podobnych problemach, i wykonałem projekt testowy, w którym, jak sądzę, udało mi się wypracować przyczynę (klasa Objective C nazywająca metodę '[self initWith ...]' w swojej publicznej metodzie 'init'), ale niestety nie ma jeszcze rozwiązań - http://stackoverflow.com/questions/31161143/non-designated-initialiser-inheritance- from-objective-c-classes – Rupert