Toutes mes excuses si cela a déjà été demandé, j'ai beaucoup cherché et beaucoup de réponses sont tirées des versions antérieures de Swift Beta lorsque la situation était différente. Je n'arrive pas à trouver une réponse définitive.
Je veux sous-classe UIViewController
et avoir un initialiseur personnalisé pour me permettre de le configurer facilement. J'ai du mal à faire ça à Swift.
Je veux une fonction init()
que je puisse utiliser pour transmettre une NSURL
spécifique que je vais ensuite utiliser avec le contrôleur de vue. Dans mon esprit, cela ressemble à quelque chose comme init(withImageURL: NSURL)
. Si j'ajoute cette fonction, il me demande ensuite d'ajouter la fonction init(coder: NSCoder)
.
Je pense que c’est parce qu’il est marqué dans la superclasse avec le mot clé required
? Je dois donc le faire dans la sous-classe? Je l'ajoute:
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
Maintenant quoi? Mon initialiseur spécial est-il considéré comme un convenience
? Un désigné? Est-ce que j'appelle un super initialiseur? Un initialiseur de la même classe?
Comment puis-je ajouter mon initialiseur spécial à une sous-classe UIViewController
?
class ViewController: UIViewController {
var imageURL: NSURL?
// this is a convenient way to create this view controller without a imageURL
convenience init() {
self.init(imageURL: nil)
}
init(imageURL: NSURL?) {
self.imageURL = imageURL
super.init(nibName: nil, bundle: nil)
}
// if this view controller is loaded from a storyboard, imageURL will be nil
/* Xcode 6
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
*/
// Xcode 7 & 8
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Les initialiseurs de commodité sont secondaires et supportent des initialiseurs pour un. classe. Vous pouvez définir un initialiseur de commodité pour appeler un .__ désigné. initialiseur de la même classe que l’initialiseur de confort avec certains paramètres de l’initialiseur désigné sont réglés sur les valeurs par défaut . Vous pouvez également définir un initialiseur de commodité pour créer une instance de cette classe pour un cas d'utilisation spécifique ou un type de valeur d'entrée.
Ils sont documentés ici .
Pour ceux qui écrivent UI en code
class Your_ViewController : UIViewController {
let your_property : String
init(your_property: String) {
self.your_property = your_property
super.init(nibName: nil, bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) is not supported")
}
}
Si vous avez besoin d'un init personnalisé pour un popover par exemple, vous pouvez utiliser l'approche suivante:
Créez un init personnalisé qui utilise le super init avec nibName et bundle puis accédez à la propriété view pour forcer le chargement de la hiérarchie des vues.
Ensuite, dans la fonction viewDidLoad, vous pouvez configurer les vues avec les paramètres transmis lors de l'initialisation.
import UIKit
struct Player {
let name: String
let age: Int
}
class VC: UIViewController {
@IBOutlet weak var playerName: UILabel!
let player: Player
init(player: Player) {
self.player = player
super.init(nibName: "VC", bundle: Bundle.main)
if let view = view, view.isHidden {}
}
override func viewDidLoad() {
super.viewDidLoad()
configure()
}
func configure() {
playerName.text = player.name + "\(player.age)"
}
}
func showPlayerVC() {
let foo = Player(name: "bar", age: 666)
let vc = VC(player: foo)
present(vc, animated: true, completion: nil)
}