Próbujesz wdrożyć init()
- niezawodny inicjator - poprzez delegowanie do init?(nibName:bundle:)
, który jest inicjatorem awaryjnym. To nie działa: jeśli wywołanie super.init
nie powiedzie się, pozostanie niezainicjowana instancja, na którą Swift nie zezwoli.
Albo, ujmując to inaczej, wynik użycia inicjalizatora awaryjnego jest opcjonalny i nie można użyć opcjonalnego zamiast wartości opcjonalnej. W przypadku inicjowania klasy i dziedziczenia nie można zastąpić nie-opcjonalnego modelu self
jako opcjonalnego - można przekazać tylko konfigurację stanu self
do innego inicjalizatora.
Zamiast tego można usunąć opcjonalności/failability z trochę pieśni i tańca:
class MainViewController: NSViewController {
override init!(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
// check state here and provide app-specific diagnostic if it's wrong
}
convenience override init() {
self.init(nibName: "MainView", bundle: nil)
}
// need this, too, or the compiler will complain that it's missing
required init?(coder: NSCoder) {
fatalError("not implemented") // ...or an actual implementation
}
}
init!
inicjator wywołuje niejawnie nieopakowanych opcjonalnego (IUO) - podobnie jak typ IUO może być użyty do pokonania między kodem który działa z wartościami opcjonalnymi i nie-opcjonalnymi, inicjator init!
może łączyć między inicjatorami awaryjnymi i niezniszczalnymi. Nie można przekazać inicjalizatora, który nie może zostać uszkodzony, do awaryjnego inicjalizatora, ale można przekazać inicjator niezawierający awarii inicjatorowi init!
i inicjatorowi init!
do inicjalizatora awaryjnego.
Tutaj inicjator NSViewController
, którego chcesz użyć, jest w pełni uszkodzony, więc zastąp go inicjalizatorem init!
. Następnie można zadeklarować niezawodny kod convenience init
, który deleguje do nowego inicjatora init!
.
Często unikają IUOs, a co za tym idzie init!
inicjatorów, ponieważ na ogół chcą jawnie zezwolić na (i wymagają obsługi) Uszkodzenie lub wyraźnie nie dopuścić do tego. Jednak jednym z najsilniejszych ogólnych przypadków użycia IUO i ich krewnych jest przekształcenie warunków, które są gwarantowane tylko poza twoim kodem źródłowym, w twierdzenia, które twój kod może traktować jako nieomylny. IBOutlet
s są tego świetnym przykładem - w swoim stalówce/scenorysie gwarantujesz stan zmiennych IBOutlet
, ale kompilator o tym nie wie - podobnie jak wszystko, co należy zrobić z zasobami pakietu.
Ten mały taniec delegacji stawia ciężar porażki w określonym, łatwym do debugowania miejscu w kodzie - jeśli połączenie od init()
do super.init(nibName:bundle:)
nie powiedzie się, twoja aplikacja zawiesi się. Ale można oczekiwać, że wezwanie do porażki nastąpi tylko w bardzo specyficznych (i głównie w trakcie rozwoju) warunkach.
szaleństwo. co powiesz na zwięzłość, proszę jabłko. –
Daje to błąd w Swift 1.2: "Inicjator nie zastępuje wyznaczonego inicjalizatora z jego nadklasy" ... to znaczy nadpisanie na 2. init musi zostać usunięte. Nawet po tym, po kompilacji trzeciego inicjalizatora zgłasza swój błąd krytyczny. Jak to musi być wdrożone? – BadmintonCat
To zbyt skomplikowane. –