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)?

BadmintonChat
la source
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()
}
BadmintonChat
la source
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)
}
Tr0yJ
la source
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.

Wlingke
la source
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
    }
}
emrcftci
la source