Comment initialiser / instancier une class UIView personnalisée avec un file XIB dans Swift

J'ai une class appelée MyClass qui est une sous-class de UIView , que je veux initialiser avec un file XIB . Je ne suis pas sûr comment initialiser cette class avec le file View.xib appelé View.xib

 class MyClass: UIView { // what should I do here? //init(coder aDecoder: NSCoder) {} ?? } 

J'ai testé ce code et ça marche super

 class MyClass: UIView { class func instanceFromNib() -> UIView { return UINib(nibName: "nib file name", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as UIView } } 

Initialiser la vue et l'utiliser comme ci-dessous

  var view = MyClass.instanceFromNib() self.view.addSubview(view) 

OU

  var view = MyClass.instanceFromNib self.view.addSubview(view()) 

UDATE Swift 3.x

 class func instanceFromNib() -> UIView { return UINib(nibName: "nib file name", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! UIView } 

À partir de Swift 2.0, vous pouvez append une extension de protocole. À mon avis, c'est une meilleure approche parce que le type de return est Self plutôt que UIView , donc l'appelant n'a pas besoin de lancer la class de vue.

 import UIKit protocol UIViewLoading {} extension UIView : UIViewLoading {} extension UIViewLoading where Self : UIView { // note that this method returns an instance of type `Self`, rather than UIView static func loadFromNib() -> Self { let nibName = "\(self)".characters.split{$0 == "."}.map(Ssortingng.init).last! let nib = UINib(nibName: nibName, bundle: nil) return nib.instantiateWithOwner(self, options: nil).first as! Self } } 

La solution de Sam est déjà géniale, bien qu'elle ne prenne pas en count différents packages (NSBundle: forClass vient à la rescousse) et nécessite un chargement manuel, c'est-à-dire un code de frappe.

Si vous voulez un support complet pour vos sorties Xib, différents bundles (utilisez dans des frameworks!) Et obtenez un bon aperçu dans Storyboard, essayez ceci:

 // NibLoadingView.swift import UIKit // Usage: Subclass your UIView from NibLoadView to automatically load a xib with the same name as your class @IBDesignable class NibLoadingView: UIView { @IBOutlet weak var view: UIView! override init(frame: CGRect) { super.init(frame: frame) nibSetup() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) nibSetup() } private func nibSetup() { backgroundColor = .clearColor() view = loadViewFromNib() view.frame = bounds view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] view.translatesAutoresizingMaskIntoConstraints = true addSubview(view) } private func loadViewFromNib() -> UIView { let bundle = NSBundle(forClass: self.dynamicType) let nib = UINib(nibName: Ssortingng(self.dynamicType), bundle: bundle) let nibView = nib.instantiateWithOwner(self, options: nil).first as! UIView return nibView } } 

Utilisez votre xib comme d'habitude, c'est-à-dire connectez les Outlets au propriétaire du file et définissez la class du propriétaire du file sur votre propre class.

Utilisation: Juste sous-classr votre propre class View de NibLoadingView.

Aucun code supplémentaire requirejs plus.

Crédits où le crédit est dû: Forked ceci avec des changements mineurs de DenHeadless sur GH. Mon Gist: https://gist.github.com/winkelsdorf/16c481f274134718946328b6e2c9a4d8

Et voici la réponse de Frederik sur Swift 3.0

 @IBDesignable class NibLoadingView: UIView { @IBOutlet weak var view: UIView! override init(frame: CGRect) { super.init(frame: frame) nibSetup() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) nibSetup() } private func nibSetup() { backgroundColor = .clear view = loadViewFromNib() view.frame = bounds view.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.translatesAutoresizingMaskIntoConstraints = true addSubview(view) } private func loadViewFromNib() -> UIView { let bundle = Bundle(for: type(of: self)) let nib = UINib(nibName: Ssortingng(describing: type(of: self)), bundle: bundle) let nibView = nib.instantiate(withOwner: self, options: nil).first as! UIView return nibView } } 

Manière universelle de charger la vue de xib:

Exemple:

 let myView = Bundle.loadView(fromNib: "MyView", withType: MyView.self) 

La mise en oeuvre:

 extension Bundle { static func loadView<T>(fromNib name: Ssortingng, withType type: T.Type) -> T { if let view = Bundle.main.loadNibNamed(name, owner: nil, options: nil)?.first as? T { return view } fatalError("Could not load view with type " + Ssortingng(describing: type)) } } 

Swift 3 Réponse: Dans mon cas, je voulais avoir un sharepoint vente dans ma class personnalisée que je pourrais modifier:

 class MyClassView: UIView { @IBOutlet weak var myLabel: UILabel! class func createMyClassView() -> MyClass { let myClassNib = UINib(nibName: "MyClass", bundle: nil) return myClassNib.instantiate(withOwner: nil, options: nil)[0] as! MyClassView } } 

Dans le file .xib, assurez-vous que le champ Classe personnalisée est MyClassView. Ne vous embêtez pas avec le propriétaire du file.

Assurez-vous que la classe personnalisée est MyClassView

En outre, assurez-vous que vous connectez la prise dans MyClassView à l'label: Outlet pour myLabel

Pour l'instancier:

 let myClassView = MyClassView.createMyClassView() myClassView.myLabel.text = "Hello World!" 
 override func draw(_ rect: CGRect) { AlertView.layer.cornerRadius = 4 AlertView.clipsToBounds = true btnOk.layer.cornerRadius = 4 btnOk.clipsToBounds = true } class func instanceFromNib() -> LAAlertView { return UINib(nibName: "LAAlertView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! LAAlertView } @IBAction func okBtnDidClicked(_ sender: Any) { removeAlertViewFromWindow() UIView.animate(withDuration: 0.4, delay: 0.0, options: .allowAnimatedContent, animations: {() -> Void in self.AlertView.transform = CGAffineTransform(scaleX: 0.1, y: 0.1) }, completion: {(finished: Bool) -> Void in self.AlertView.transform = CGAffineTransform.identity self.AlertView.transform = CGAffineTransform(scaleX: 0.0, y: 0.0) self.AlertView.isHidden = true self.AlertView.alpha = 0.0 self.alpha = 0.5 }) } func removeAlertViewFromWindow() { for subview in (appDel.window?.subviews)! { if subview.tag == 500500{ subview.removeFromSuperview() } } } public func openAlertView(title:Ssortingng , ssortingng : Ssortingng ){ lblTital.text = title txtView.text = ssortingng self.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight) appDel.window!.addSubview(self) AlertView.alpha = 1.0 AlertView.isHidden = false UIView.animate(withDuration: 0.2, animations: {() -> Void in self.alpha = 1.0 }) AlertView.transform = CGAffineTransform(scaleX: 0.0, y: 0.0) UIView.animate(withDuration: 0.3, delay: 0.2, options: .allowAnimatedContent, animations: {() -> Void in self.AlertView.transform = CGAffineTransform(scaleX: 1.1, y: 1.1) }, completion: {(finished: Bool) -> Void in UIView.animate(withDuration: 0.2, animations: {() -> Void in self.AlertView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) }) }) }