2015-07-18 28 views
7

EDIT: Ecco tutta code example per Xcode 6.4viewDidLoad viene chiamato prima il metodo init tutto viene eseguito

ho semplice applicazione iOS, senza storyboard. Ho impostato rootViewController per UIWindow in AppDelegate.swift come questo:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
    let tabBarController = TabBarController() 

    window = UIWindow(frame: UIScreen.mainScreen().bounds) 
    window?.rootViewController = tabBarController 
    window?.makeKeyAndVisible() 

    return true 
} 

TabBarController implementazione della classe è la seguente:

class TabBarController: UITabBarController { 

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { 
     super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 

     // Next line is called after 'viewDidLoad' method 
     println("init(nibName: bundle:)") 
    } 

    required init(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     println("viewDidLoad") 
    } 

} 

Quando eseguo applicazione l'uscita della console si presenta così:

viewDidLoad 
init(nibName: bundle:) 

E ' significa che le linee dopo la linea super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) vengono chiamate dopo il metodo viewDidLoad! Ciò si verifica solo per le classi che ereditano da UITabBarController. Se provi questo stesso esempio con il discendente UIViewController, tutto è ok e viewDidLoad viene chiamato dopo l'esecuzione del metodo init.

risposta

8

Non è garantito che lo viewDidLoad venga chiamato solo dopo aver eseguito il metodo init. viewDidLoad viene chiamato quando un controller di visualizzazione deve caricare la sua gerarchia di viste.

Internamente, il metodo init di TabBarController (chiamando super.init) sta facendo qualcosa che sta causando il caricamento della vista.

Questo vale per tutti i controller di vista. Ad esempio: se si crea una sottoclasse UIViewController e si fa qualcosa con la sua proprietà view su init, come aggiungere una sottoview, o anche solo impostare la proprietà backgroundColor della vista, si noterà lo stesso comportamento.

+1

Grazie. Ma penso che questo sia un comportamento incoerente e non è ben documentato. Invio TSI ad Apple e sono interessato a vedere la loro risposta. – Deny

+0

@Deny Mi piacerebbe sentire quello che Apple ha da dire quando ti danno una risposta, ma ho il sospetto che non sarà possibile ottenere molte informazioni aggiuntive. Questo è un comportamento standard di iOS. Hai ragione per quanto riguarda la mancanza di documentazione per la sottoclasse TabBarController. – Artal

1

Sembra che init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) per un UITabBarController chiama viewDidLoad per qualche motivo. Se si imposta un punto di interruzione sulla linea print("viewDidLoad"), si vedrà che la chiamata viene effettuata come parte della sequenza di inizializzazione.

Se si cambia il controller della vista di sottoclasse UIViewController vedrete che viewDidLoad non si chiama come parte della sequenza di inizializzazione, ma piuttosto come conseguenza della chiamata makeKeyAndVisible

Non so il motivo per cui Apple ha codificato in questo modo, ma ho il sospetto che sia per dare al controller della barra delle schede l'opportunità di impostare le cose prima che i controller della vista del contenuto siano caricati.

Indipendentemente da ciò, è solo qualcosa che si sta per avere a che fare con se si vuole creare una sottoclasse UITabBarController

+0

Hai ragione. Sono giunto alla stessa conclusione. Anche così, sono curioso di commentare i tecnici Apple. Lo posterò qui allora. – Deny

5

Da: http://www.andrewmonshizadeh.com/2015/02/23/uitabbarcontroller-is-different/

questo dovrebbe venire come nessuna sorpresa, ma a quanto pare UITabBarController ha un comportamento diverso da quello la maggior parte dei controller di visualizzazione. Il ciclo di vita può essere in generale lo "stesso" tra esso e altri controller di vista, ma l'ordine che esegue non lo è.

Cioè, quando si crea una sottoclasse di UITabBarController e si fornisce il proprio inizializzatore personalizzato, si noterà che il metodo viewDidLoad viene chiamato in modo inaspettato. Cioè, non appena chiami [super init] (o un altro inizializzatore su UITabBarController), chiamerà loadView durante quell'inizializzazione che porterà al fatto che viewDidLoad viene chiamato. Questo probabilmente non è quello che ti aspetteresti perché la maggior parte (tutto?) Altre sottoclassi UIViewController non istanziare loro vista durante il processo di inizializzazione. In quanto tale, se hai fornito un inizializzatore personalizzato e aspetta di fare alcune operazioni di configurazione prima che la vista è caricato, e poi una volta la vista è caricato aggiungere i controller di vista contenute, questo si romperà la vostra logica.

La soluzione è quella di spostare effettivamente il tuo codice di installazione fuori del metodo viewDidLoad standard ed in un metodo di configurazione speciale che è chiamato alla fine della vostra inizializzatore personalizzato. Questo mi sembra un "odore di codice" che Apple non avrebbe mai dovuto lasciare passare. Probabilmente, però, questo è perché l'UITabBarController bisogno di aggiungere un UITabBar alla visualizzazione del UIViewController che richiede che la vista esiste. Qual è ciò che spara loadView.