2016-12-21 33 views
14

Mam podklasy UINavigationController i UITableViewController.Inicjalizacja wygodna podklasy UINavigationController sprawia, że ​​podklasa stała init init dwa razy

Do inicjowania podklas postanowiłem zastosować pewne metody, które wywołują niektóre wyznaczone inicjatory superklasy. Ponadto, każda podklasa ma pewne let Constant:

let someValue: SomeClass = SomeClass() 

Każda klasa jest pomyślnie zainicjowany przez wywołanie nowo utworzonego convenience init metody.

Problem polega na tym, że stała let jest inicjowana TWICE w podklasie UINavigationController.

import UIKit 
import PlaygroundSupport 

final class Navigation: UINavigationController { 
    convenience init(anyObject: Any) { 
     self.init(rootViewController: UIViewController()) 
    } 
    let service = Constant("Constant Initialization -> Navigation") 
} 

final class Table: UITableViewController { 
    convenience init(anyObject: Any) { 
     self.init(style: .plain) 
    } 
    let service = Constant("Constant Initialization -> Table") 
} 

class Constant: NSObject { 
    init(_ string: String) { 
     super.init() 
     debugPrint(string) 
    } 
} 

Navigation(anyObject: NSNull()) 
Table(anyObject: NSNull()) 

Czy możemy używać convenience init jak wyżej? Czemu?

Dlaczego zachowanie w obu przypadkach jest inne niż w przypadku convenience init?

sprawdzone w: wersja 8.2 beta (8C30a), wersja 8,2 (8C38), Version 8.2.1 (8C1002)

P.S. Dziennik plac zabaw dla kodu powyżej:

"Constant Initialization -> Navigation" 
"Constant Initialization -> Navigation" 
"Constant Initialization -> Table" 

Odpowiedz

3

To wydaje się dziwne "oczekiwane zachowanie" u Swifta. Powodem tego jest stała inicjowana własność service. Mianowicie, ten post podsumowuje wystawia widząc całkiem dobrze: Pamięć blog post

Zasadniczo, Obj-C bazowe Super zajęcia przeciekają i nieruchomość service inicjowany jest dwukrotnie z powodu tego wzoru Obj-C inicjalizacji:

- (id)init { 
    self = [super init]; 
    if (self) { 
    self = [[self.class alloc] initWithNibName:nil bundle:nil]; 
    } 
    return self; 
} 

prostym rozwiązaniem tego uniknąć jest następujący wzór:

import UIKit 

final class NavigationController: UINavigationController { 
    var service: ObjectTest? 

    convenience init() { 
     self.init(rootViewController: UIViewController()) 
     self.service = ObjectTest("init nav") 
    } 
} 
class ObjectTest: NSObject{ 
    init(_ string: String) { 
     super.init() 
     print(string) 
    } 
} 

Wszystko, co zmienia się od implementacji jest inicjowanie service dopiero po yo została zainicjowana sama klasa.

Innym rozwiązaniem jest użycie wyznaczonego inicjalizatora dla nadklasy, którą inicjalizujesz. Oznacza to, że nie korzystasz z inicjalizatora wygody, który wykorzystałby powyższy schemat inicjalizacji Obj-C.

+0

Dziękuję za odpowiedź. I nadal nie rozumiem, dlaczego zachowanie inicjacji wygody jest inne w tych dwóch przypadkach? – iWheelBuy

+0

Tak więc inicjalizacja "wygody" używa powyższego wzorca inicjacji Objective-C, gdzie są dwa wywołania inicjujące ('[super init]' i '[self.class alloc] init ...]'. Wskazany inicjator, od mojego zrozumienie, trafiłoby bezpośrednio do ścieżki inicjującej '[self.class alloc] ... '' inicjatora, a zatem nie podwójnie zainicjowałoby, co jest przyczyną problemu, który widzisz .. – BHendricks

+0

Myślałem, że w obu przypadkach Wzywam wyznaczonego inicjatora, prawda? – iWheelBuy