web-dev-qa-db-fra.com

Comment écrire un init personnalisé pour une sous-classe UIView dans Swift?

Dites que je veux init une UIView sous-classe avec un String et un Int.

Comment ferais-je cela dans Swift si je ne fais que sous-classer UIView? Si je crée simplement une fonction init() personnalisée mais que les paramètres sont une chaîne et un int, cela me dit que "super.init () n'est pas appelé avant le retour de l'initialiseur".

Et si j'appelle super.init() on me dit que je dois utiliser un initialiseur désigné. Que devrais-je utiliser là-bas? La version du cadre? La version du codeur? Tous les deux? Pourquoi?

108
Doug Smith

La version init(frame:) est l'initialiseur par défaut. Vous ne devez l'appeler qu'après avoir initialisé vos variables d'instance. Si cette vue est reconstituée à partir d'un NIB, votre initialiseur personnalisé ne sera pas appelé, mais la version init?(coder:) sera appelée. Puisque Swift nécessite maintenant une implémentation de la init?(coder:) requise, j'ai mis à jour l'exemple ci-dessous et modifié les déclarations de variable let en var et facultatif. Dans ce cas, vous les initialiserez dans awakeFromNib() ou ultérieurement.

class TestView : UIView {
    var s: String?
    var i: Int?
    init(s: String, i: Int) {
        self.s = s
        self.i = i
        super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}
175
Wolf McNally

Je crée un init commun pour le désigné et requis. Par commodité, je délègue à init(frame:) avec une trame égale à zéro.

Avoir zéro image n'est pas un problème car généralement, la vue est dans la vue d'un ViewController; votre vue personnalisée aura une bonne chance de mettre en forme ses sous-vues lorsque sa vue supérieure appelle layoutSubviews() ou updateConstraints(). Ces deux fonctions sont appelées par le système de manière récursive dans la hiérarchie des vues. Vous pouvez utiliser updateContstraints() ou layoutSubviews(). updateContstraints() est appelé en premier, puis layoutSubviews(). Dans updateConstraints() assurez-vous d'appeler super dernier. Dans layoutSubviews(), appelez super premier.

Voici ce que je fais:

@IBDesignable
class MyView: UIView {

      convenience init(args: Whatever) {
          self.init(frame: CGRect.zero)
          //assign custom vars
      }

      override init(frame: CGRect) {
           super.init(frame: frame)
           commonInit()
      }

      required init?(coder aDecoder: NSCoder) {
           super.init(coder: aDecoder)
           commonInit()
      }

      override func prepareForInterfaceBuilder() {
           super.prepareForInterfaceBuilder()
           commonInit()
      }

      private func commonInit() {
           //custom initialization
      }

      override func updateConstraints() {
           //set subview constraints here
           super.updateConstraints()
      }

      override func layoutSubviews() {
           super.layoutSubviews()
           //manually set subview frames here
      }

}
22
MH175

Voici comment je le fais sur iOS 9 dans Swift -

import UIKit

class CustomView : UIView {

    init() {
        super.init(frame: UIScreen.mainScreen().bounds);

        //for debug validation
        self.backgroundColor = UIColor.blueColor();
        print("My Custom Init");

        return;
    }

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

Voici un projet complet avec exemple:

17
J-Dizzle

Voici comment je fais une sous-vue sur iOS dans Swift -

class CustomSubview : UIView {

    init() {
        super.init(frame: UIScreen.mainScreen().bounds);

        let windowHeight : CGFloat = 150;
        let windowWidth  : CGFloat = 360;

        self.backgroundColor = UIColor.whiteColor();
        self.frame = CGRectMake(0, 0, windowWidth, windowHeight);
        self.center = CGPoint(x: UIScreen.mainScreen().bounds.width/2, y: 375);

        //for debug validation
        self.backgroundColor = UIColor.grayColor();
        print("My Custom Init");

        return;
    }

    required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented"); }
}
9
J-Dizzle