Swift: initialiseurs ViewController personnalisés


87

Comment ajouter des initialiseurs personnalisés aux UIViewControllersous-classes dans Swift?

J'ai créé une sous-classe de UIViewControllerqui ressemble à ceci:

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

        super.init();

        setupScrollView();
        setupViewControllers();
    }
}

Lorsque je l'exécute, j'obtiens une erreur fatale:

erreur fatale: utilisation de l'initialiseur non implémenté 'init (nibName: bundle :)' pour la classe 'MyApp.MyViewController'

J'ai lu ailleurs que lors de l'ajout d'un initialiseur personnalisé, il faut également remplacer, init(coder aDecoder:NSCoder)alors remplaçons cela initet voyons ce qui se passe:

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

Si j'ajoute cela, Xcode s'en plaint self.leftVC is not initialized at super.init call. Je suppose donc que cela ne peut pas non plus être la solution. Je me demande donc comment puis-je ajouter correctement des initialiseurs personnalisés à une ViewControllersous - classe dans Swift (puisque dans Objective-C cela ne semble pas être un problème)?


Comment essayez-vous d'instancier votre MyViewController?
Mike Pollard

Pourquoi ne pas tout instancier dans viewDidLoad (), là vous pouvez les initialiser comme vous le souhaitez
tudoricc

@MikePollard avec dualViewCtrl = DualViewCtrl (leftVC: l, rightVC: r, gap: 50) ... J'ai déjà découvert que je devais utiliser l'initialiseur initWithNib.
BadmintonCat

3
@tudoricc Parce que vous voulez souvent des propriétés d'instance qui sont initialisées en toute sécurité dans l'initialiseur avec des paramètres donnés. Vous ne pouvez pas faire cela dans viewDidLoad car il ne serait pas garanti que les propriétés soient disponibles en cas de besoin.
BadmintonCat

Je suis désolé, c'est juste que dans mon esprit je vois le viewDidLoad () comme un initialiseur. merci pour l'explication
tudoricc

Réponses:


124

Résolu! Il faut appeler l'initialiseur désigné qui dans ce cas est le init avec nibName, évidemment ...

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
Débarrassez-vous de ces vilains points-virgules :)
MobileMon

8
J'aime les points-virgules. Ils rendent le code moins ambigu, en particulier avec ces noms et signatures d'API Cocoa / Cocoa-Touch ridiculement verbeux. Mauvaise décision des concepteurs Swift de les supprimer à mon humble avis.
BadmintonCat

25
IMHO, si vous tapez un caractère et que cela n'affecte pas le binaire compilé, vous ne devriez pas le taper :)
Sam Soffes

32
@SamSoffes pour ne pas utiliser du tout d'espaces (supplémentaires)? Et vous obscurcissez tous les symboles pour devenir des caractères uniques?
Victor Jalencas

8
Cette discussion me rappelle les onglets vs espaces dans la Silicon Valley
Aaron

13

Pour un UIViewController plus générique, vous pouvez l'utiliser à partir de Swift 2.0

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

11

Je ne sais pas si vous avez réussi à résoudre complètement cela ... mais en fonction de l'apparence de l'interface de votre classe et du besoin ou non de la fonctionnalité de codeur, vous pouvez également utiliser ce qui suit:

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

Puisqu'il init:leftVC:rightVC:gaps'agit d'un initialiseur désigné, vous pouvez remplir l'exigence d'implémentationinit:coder en en en faisant un initialiseur pratique qui appelle votre initialiseur désigné.

Cela pourrait être mieux que

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

car si vous avez besoin d'initialiser certaines propriétés, vous devrez les réécrire.


8

Swift 5

Si vous souhaitez écrire un initialiseur personnalisé sur UIViewControllerlequel est initialisé avecstoryBoard.instantiateViewController(withIdentifier: "ViewControllerIdentifier")

Vous pouvez écrire un initialiseur personnalisé uniquement pour les Optionalpropriétés.

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
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.