2014-06-07 9 views
50

Non sto usando un UIViewController da StoryBoards e voglio avere una funzione init personalizzata dove passo in un NSManagedObjectID di qualche oggetto. Voglio solo chiamare super.init() come ho nell'obiettivo c. Così:Perché non posso chiamare il super.init predefinito() su UIViewController in Swift?

init(objectId : NSManagedObjectID) { 
    super.init() 
} 

Ma non posso compilare con quello. Posso semplicemente non farlo più?

Il messaggio di errore del compilatore ottengo: "deve chiamare inizializzatore designato della UIViewController superclasse"

risposta

73

L'initialiser designato per UIViewController è initWithNibName:bundle:. Dovresti chiamarlo invece.

Vedi http://www.bignerdranch.com/blog/real-iphone-crap-2-initwithnibnamebundle-is-the-designated-initializer-of-uiviewcontroller/

Se non si dispone di un pennino, passa in nil per il nibName (bundle è facoltativo troppo). Quindi è possibile creare una visualizzazione personalizzata in loadView o aggiungendo subviews a self.view in viewDidLoad, come in passato.

+3

Così è attualmente impossibile per me fare un metodo init personalizzato in una sottoclasse UIViewController che non è da un pennino? – KKendall

+1

Ah, grazie !! Stavo passando "" per il nome del pennino. – KKendall

+0

Overriding 'initWithNibName: bundle:' alone non è sufficiente; il compilatore genera un errore e suggerisce di implementare anche il (richiesto) 'initWithCoder:'. Immagino che entrambi siano inizializzatori designati? Ma solo 'withCoder' viene contrassegnato come" richiesto "in swift ... –

32

Un'altra bella soluzione è quella di dichiarare il vostro nuovo inizializzatore come convenience inizializzatore come segue:

convenience init(objectId : NSManagedObjectID) { 
    self.init() 

    // ... store or user your objectId 
} 

Se si dichiara non inizializzatori designati nella sottoclasse a tutti, sono ereditate automaticamente e sono in grado di utilizzare self.init() nel tuo inizializzatore di convenienza.

In caso di UIViewController, il metodo di inizializzazione predefinito chiamerà init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) con nil per entrambi gli argomenti (Command-Click su UIViewController fornirà tali informazioni).

TL; TR: Se si preferisce lavorare a livello di codice con UIViewController s qui è un esempio di lavoro completo che aggiunge un nuovo inizializzatore con un argomento personalizzato:

class MyCustomViewController: UIViewController { 
    var myString: String = "" 

    convenience init(myString: String) { 
     self.init() 

     self.myString = myString 
    } 
} 
+0

Questa è una soluzione più elegante e funziona in qualsiasi caso generico – Ciprian

+2

Ho provato a farlo in un'estensione e si chiamava in modo ricorsivo. –

+0

@DanyalAytekin quando fornisci il tuo codice come sintesi, posso dirti perché. – Klaas

2

Secondo la documentazione per iOS, i inizializzatore designato per UIViewController è initWithNibName: bundle:.

Se si sottoclasse UIViewController, è necessario chiamare la super implementazione di questo metodo, anche se non si utilizza un NIB.

Si può fare come segue:

init(objectId : NSManagedObjectID) { 

    super.init(nibName: (xib's name or nil'), bundle: nil) 

    // other code... 
} 

o

dichiarare una nuova inizializzatore come inizializzatore convenienza:

convenience init(objectId : NSManagedObjectID) { 

    self.init() 

    // other code... 

}

+1

È necessario collegare l'originale per l'attribuzione, anziché lasciarlo come screencap. –

+0

Ho usato lo stesso processo di @NcNc detto. Ha funzionato per me. Ecco [collegamento] (https://stackoverflow.com/questions/40997236/super-init-isnt-called-on-all-paths-before-returning-from-initializer/45920375#45920375) –

3

Per migliorare risposta del occulus:

init() { 
    super.init(nibName: nil, bundle: nil) 
} 
Problemi correlati