Swift: inizializzatori ViewController personalizzati


87

Come si aggiungono inizializzatori personalizzati alle UIViewControllersottoclassi in Swift?

Ho creato una sottoclasse UIViewControllersimile a questa:

class MyViewController : UIViewController
{
    init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
    {
        self.leftVC = leftVC;
        self.rightVC = rightVC;
        self.gap = gap;

        super.init();

        setupScrollView();
        setupViewControllers();
    }
}

Quando lo eseguo ricevo un errore fatale:

errore irreversibile: utilizzo dell'inizializzatore non implementato 'init (nibName: bundle :)' per la classe 'MyApp.MyViewController'

Ho letto ovunque che quando si aggiunge un inizializzatore personalizzato si deve anche eseguire l'override, init(coder aDecoder:NSCoder)quindi sovrascriviamolo inite vediamo cosa succede:

override init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder);
}

Se aggiungo questo, Xcode se ne lamenta self.leftVC is not initialized at super.init call. Quindi immagino che nemmeno questa possa essere la soluzione. Quindi mi chiedo come posso aggiungere correttamente inizializzatori personalizzati a una ViewControllersottoclasse in Swift (poiché in Objective-C questo sembra non essere un problema)?


Come stai cercando di istanziare il tuo MyViewController?
Mike Pollard,

Perché non istanziare tutto in viewDidLoad (), lì puoi inizializzarli nel modo desiderato
tudoricc

@MikePollard con dualViewCtrl = DualViewCtrl (leftVC: l, rightVC: r, gap: 50) ... Ho già scoperto che devo usare l'inizializzatore initWithNib.
BadmintonCat

3
@tudoricc Perché spesso vuoi proprietà di istanza che siano inizializzate in modo sicuro nell'inizializzatore con parametri dati. Non puoi farlo in viewDidLoad da allora non sarebbe garantito che le proprietà siano disponibili quando necessario.
Badminton

Mi dispiace è solo che nella mia mente vedo viewDidLoad () come inizializzatore. grazie per la spiegazione
tudoricc

Risposte:


124

Risolto! Bisogna chiamare l'inizializzatore designato che in questo caso è l'init con nibName, ovviamente ...

init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
{
    self.leftVC = leftVC
    self.rightVC = rightVC
    self.gap = gap

    super.init(nibName: nil, bundle: nil)

    setupScrollView()
    setupViewControllers()
}

31
Sbarazzati di quei brutti punti e virgola :)
MobileMon

8
Mi piacciono i punti e virgola. Rendono il codice meno ambiguo, specialmente con quei nomi e le firme API Cocoa / Cocoa-Touch ridicolmente prolissi. Pessima decisione dei designer Swift di rimuoverli IMHO.
Badminton

25
IMHO, se digiti un carattere e non ha effetto sul binario compilato, non dovresti digitarlo :)
Sam Soffes

32
@SamSoffes quindi non usi affatto spazi (extra)? E offuschi tutti i simboli in modo che siano singoli caratteri?
Victor Jalencas

8
Questa discussione mi ricorda le schede e gli spazi nella Silicon Valley
Aaron

13

Per un UIViewController più generico puoi usarlo a partire da Swift 2.0

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

11

Non sono sicuro se sei riuscito a risolverlo completamente ... ma a seconda di come desideri che l'interfaccia della tua classe appaia e se hai effettivamente bisogno della funzionalità di codificatore, puoi anche usare quanto segue:

convenience required init(coder aDecoder: NSCoder)
{
    //set some defaults for leftVC, rightVC, and gap
    self.init(leftVC, rightVC, gap)
}

Poiché init:leftVC:rightVC:gapè un inizializzatore designato, è possibile soddisfare il requisito di implementazione init:coderrendendolo un inizializzatore di convenienza che chiama l'inizializzatore designato.

Questo potrebbe essere migliore di

override init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder);
}

perché se è necessario inizializzare alcune proprietà, sarà necessario riscriverle.


8

Swift 5

Se vuoi scrivere un inizializzatore personalizzato su UIViewControllercui viene inizializzato constoryBoard.instantiateViewController(withIdentifier: "ViewControllerIdentifier")

È possibile scrivere un inizializzatore personalizzato solo per le Optionalproprietà.

class MyFooClass: UIViewController {
    var foo: Foo?

    init(with foo: Foo) {
        self.foo = foo
        super.init(nibName: nil, bundle: nil)
    }

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.foo = nil
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.