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?
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)
}
}
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
}
}
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:
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"); }
}