Chargez un UIView à partir de nib dans Swift

Voici mon code Objective-C que j’utilise pour charger un nib pour mon UIView personnalisé:

 -(id)init{ NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"myXib" owner:self options:nil]; return [subviewArray objectAtIndex:0]; } 

Quel est le code équivalent dans Swift?

    Solution Orignal

    1. J’ai créé un XIB et une classe nommée SomeView (utilisé le même nom pour plus de commodité et de lisibilité). Je me suis basé sur un UIView.
    2. Dans XIB, j’ai changé la classe “File’s Owner” en SomeView (dans l’inspecteur d’identité).
    3. J’ai créé un sharepoint vente UIView dans SomeView.swift, en le liant à la vue de niveau supérieur du fichier XIB (nommé “view” pour plus de commodité). J’ai ensuite ajouté d’autres sorties aux autres contrôles du fichier XIB, selon les besoins.
    4. dans SomeView.swift, j’ai chargé le XIB dans l’initialiseur “init with code”. Il n’y a pas besoin d’atsortingbuer quoi que ce soit à “soi”. Dès que le XIB est chargé, toutes les sockets sont connectées, y compris la vue de niveau supérieur. La seule chose qui manque, c’est d’append la vue de dessus à la hiérarchie des vues:

    .

     class SomeView: UIView { required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) NSBundle.mainBundle().loadNibNamed("SomeView", owner: self, options: nil) self.addSubview(self.view); // adding the top level view to the view hierarchy } ... } 

    Notez que de cette façon, j’obtiens une classe qui se charge depuis nib. Je pourrais ensuite utiliser SomeView en tant que classe chaque fois qu’UIView pourrait être utilisé dans le projet (dans le générateur d’interface ou par programme).

    Update – en utilisant la syntaxe Swift 3

    Le chargement d’un fichier xib dans l’extension suivante est écrit en tant que méthode d’instance, qui peut ensuite être utilisée par un initialiseur comme celui ci-dessus:

     extension UIView { @discardableResult // 1 func fromNib() -> T? { // 2 guard let contentView = Bundle(for: type(of: self)).loadNibNamed(Ssortingng(describing: type(of: self)), owner: self, options: nil)?.first as? T else { // 3 // xib not loaded, or its top view is of the wrong type return nil } self.addSubview(contentView) // 4 contentView.translatesAutoresizingMaskIntoConstraints = false // 5 contentView.layoutAttachAll(to: self) // 6 return contentView // 7 } } 
    1. Utiliser une valeur de retour irrécupérable, car la vue renvoyée n’a pour la plupart aucun intérêt pour l’appelant lorsque tous les points de vente sont déjà connectés.
    2. C’est une méthode générique qui retourne un object optionnel de type UIView. S’il ne parvient pas à charger la vue, il renvoie nil.
    3. Tentative de chargement d’un fichier XIB portant le même nom que l’instance de classe en cours. Si cela échoue, nil est renvoyé.
    4. Ajout de la vue de niveau supérieur à la hiérarchie de vues.
    5. Cette ligne suppose que nous utilisons des contraintes pour mettre en forme la vue.
    6. Cette méthode ajoute des contraintes de haut, de bas, de début et de fin – en associant la vue à “self” sur tous les côtés (voir: https://stackoverflow.com/a/46279424/2274829 pour plus de détails)
    7. Retourner la vue de haut niveau

    Et la méthode d’appel pourrait ressembler à ceci:

     final class SomeView: UIView { // 1. required init?(coder aDecoder: NSCoder) { // 2 - storyboard initializer super.init(coder: aDecoder) fromNib() // 5. } init() { // 3 - programmatic initializer super.init(frame: CGRect.zero) // 4. fromNib() // 6. } // other methods ... } 
    1. SomeClass est une sous-classe UIView qui charge son contenu à partir d’un fichier SomeClass.xib. Le mot clé “final” est facultatif.
    2. Un initialiseur lorsque la vue est utilisée dans un storyboard (n’oubliez pas d’utiliser SomeClass comme classe personnalisée de votre vue de storyboard).
    3. Un initialiseur pour quand la vue est créée par programmation (c’est-à-dire: “let myView = SomeView ()”).
    4. Utiliser un cadre de zéros car cette vue est mise en page à l’aide de la mise en page automatique. Notez qu’une méthode “init (frame: CGRect) {..}” n’est pas créée indépendamment, car la mise en page automatique est utilisée exclusivement dans notre projet.
    5. & 6. Charger le fichier xib en utilisant l’extension.

    Crédit: L’utilisation d’une extension générique dans cette solution a été inspirée par la réponse de Robert ci-dessous.

    Modifier Changer “view” en “contentView” pour éviter toute confusion. Également changé l’indice de tableau pour “.first”.

    Ma consortingbution:

    Swift 3 / Swift 4

     extension UIView { class func fromNib() -> T { return Bundle.main.loadNibNamed(Ssortingng(describing: T.self), owner: nil, options: nil)![0] as! T } } 

    Alors appelez comme ceci:

     let myCustomView: CustomView = UIView.fromNib() 

    ..ou même:

     let myCustomView: CustomView = .fromNib() 

    Voici une extension qui utilise des génériques pour charger un UIView partir d’un nib

     public extension UIView { public class func fromNib(nibNameOrNil: Ssortingng? = nil) -> Self { return fromNib(nibNameOrNil, type: self) } public class func fromNib(nibNameOrNil: Ssortingng? = nil, type: T.Type) -> T { let v: T? = fromNib(nibNameOrNil, type: T.self) return v! } public class func fromNib(nibNameOrNil: Ssortingng? = nil, type: T.Type) -> T? { var view: T? let name: Ssortingng if let nibName = nibNameOrNil { name = nibName } else { // Most nibs are demangled by practice, if not, just declare ssortingng explicitly name = nibName } let nibViews = NSBundle.mainBundle().loadNibNamed(name, owner: nil, options: nil) for v in nibViews { if let tog = v as? T { view = tog } } return view } public class var nibName: Ssortingng { let name = "\(self)".componentsSeparatedBySsortingng(".").first ?? "" return name } public class var nib: UINib? { if let _ = NSBundle.mainBundle().pathForResource(nibName, ofType: "nib") { return UINib(nibName: nibName, bundle: nil) } else { return nil } } } 

    Je préfère cela car il ne nécessite aucune configuration supplémentaire dans la plume. Il est basé sur des conventions de dénomination générales, donc si votre classe est CustomView , et qu’elle correspond à un nib nommé: CustomView , vous pouvez simplement faire ceci:

     let myCustomView = CustomView.fromNib() // or if you're unsure whether or not the nib exists let myCustomView: CustomView? = CustomView.fromNib() 

    Si vous avez besoin d’être précis sur le nom de la plume, quelle que soit la raison, transmettez une chaîne arg:

     let myCustomView = MyCustomView.fromNib("non-conventional-name") 

    Problèmes connus

    Utiliser ceci avec une classe de vue privée semble causer des problèmes. Cela semble être un problème à l’échelle du système.

    Essayez le code suivant.

     var uiview :UIView? self.uiview = NSBundle.mainBundle().loadNibNamed("myXib", owner: self, options: nil)[0] as? UIView 

    Modifier:

     import UIKit class TestObject: NSObject { var uiview:UIView? init() { super.init() self.uiview = NSBundle.mainBundle().loadNibNamed("myXib", owner: self, options: nil)[0] as? UIView } } 

    J’ai réalisé ceci avec Swift par le code suivant:

     class Dialog: UIView { @IBOutlet var view:UIView! override init(frame: CGRect) { super.init(frame: frame) self.frame = UIScreen.mainScreen().bounds NSBundle.mainBundle().loadNibNamed("Dialog", owner: self, options: nil) self.view.frame = UIScreen.mainScreen().bounds self.addSubview(self.view) } required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } } 

    N’oubliez pas de connecter votre prise de vue XIB pour voir la prise définie dans swift. Vous pouvez également définir First Responder sur votre nom de classe personnalisé pour commencer à connecter des points de vente supplémentaires.

    J’espère que cela t’aides!

    Testé dans Xcode 7 beta 4, Swift 2.0 et iOS9 SDK. Le code suivant affectera xib à la vue uiview. Vous pouvez utiliser cette vue xib personnalisée dans storyboard et accéder également à l’object IBOutlet.

     import UIKit @IBDesignable class SimpleCustomView:UIView { var view:UIView!; @IBOutlet weak var lblTitle: UILabel! @IBInspectable var lblTitleText : Ssortingng? { get{ return lblTitle.text; } set(lblTitleText) { lblTitle.text = lblTitleText!; } } override init(frame: CGRect) { super.init(frame: frame) loadViewFromNib () } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) loadViewFromNib () } func loadViewFromNib() { let bundle = NSBundle(forClass: self.dynamicType) let nib = UINib(nibName: "SimpleCustomView", bundle: bundle) let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView view.frame = bounds view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] self.addSubview(view); } } 

    Accéder à la vue personnalisée par programmation

     self.customView = SimpleCustomView(frame: CGRectMake(100, 100, 200, 200)) self.view.addSubview(self.customView!); 

    Code source – https://github.com/karthikprabhuA/CustomXIBSwift

    Si vous avez beaucoup de vues personnalisées dans votre projet, vous pouvez créer une classe comme UIViewFromNib

    Swift 2.3

     class UIViewFromNib: UIView { var contentView: UIView! var nibName: Ssortingng { return Ssortingng(self.dynamicType) } //MARK: override init(frame: CGRect) { super.init(frame: frame) loadViewFromNib() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) loadViewFromNib() } //MARK: private func loadViewFromNib() { contentView = NSBundle.mainBundle().loadNibNamed(nibName, owner: self, options: nil)[0] as! UIView contentView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] contentView.frame = bounds addSubview(contentView) } } 

    Swift 3

     class UIViewFromNib: UIView { var contentView: UIView! var nibName: Ssortingng { return Ssortingng(describing: type(of: self)) } //MARK: override init(frame: CGRect) { super.init(frame: frame) loadViewFromNib() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) loadViewFromNib() } //MARK: func loadViewFromNib() { contentView = Bundle.main.loadNibNamed(nibName, owner: self, options: nil)?[0] as! UIView contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] contentView.frame = bounds addSubview(contentView) } } 

    Et dans chaque classe héritant de UIViewFromNib , vous pouvez également remplacer la propriété .xib si le fichier .xib a un nom différent:

     class MyCustomClass: UIViewFromNib { } 

    S’appuyant sur les solutions ci-dessus.

    Cela fonctionnera sur tous les ensembles de projets et pas besoin de génériques lorsque vous appelez deNib ().

    Swift 2

     extension UIView { public class func fromNib() -> Self { return fromNib(nil) } public class func fromNib(nibName: Ssortingng?) -> Self { func fromNibHelper(nibName: Ssortingng?) -> T { let bundle = NSBundle(forClass: T.self) let name = nibName ?? Ssortingng(T.self) return bundle.loadNibNamed(name, owner: nil, options: nil)?.first as? T ?? T() } return fromNibHelper(nibName) } } 

    Swift 3

     extension UIView { public class func fromNib() -> Self { return fromNib(nibName: nil) } public class func fromNib(nibName: Ssortingng?) -> Self { func fromNibHelper(nibName: Ssortingng?) -> T where T : UIView { let bundle = Bundle(for: T.self) let name = nibName ?? Ssortingng(describing: T.self) return bundle.loadNibNamed(name, owner: nil, options: nil)?.first as? T ?? T() } return fromNibHelper(nibName: nibName) } } 

    Peut être utilisé comme ceci:

     let someView = SomeView.fromNib() 

    Ou comme ça:

     let someView = SomeView.fromNib("SomeOtherNibFileName") 

    Une bonne façon de faire cela avec Swift est d’utiliser un enum.

     enum Views: Ssortingng { case view1 = "View1" // Change View1 to be the name of your nib case view2 = "View2" // Change View2 to be the name of another nib func getView() -> UIView { return NSBundle.mainBundle().loadNibNamed(self.rawValue, owner: nil, options: nil)[0] as! UIView } } 

    Ensuite, dans votre code, vous pouvez simplement utiliser:

     let view = Views.view1.getView() 

    Je préfère cette solution (basée sur la réponse si @ GK100):

    1. J’ai créé un XIB et une classe nommée SomeView (utilisé le même nom pour plus de commodité et de lisibilité). Je me suis basé sur un UIView.
    2. Dans XIB, j’ai changé la classe “File’s Owner” en SomeView (dans l’inspecteur d’identité).
    3. J’ai créé un sharepoint vente UIView dans SomeView.swift, en le liant à la vue de niveau supérieur du fichier XIB (nommé “view” pour plus de commodité). J’ai ensuite ajouté d’autres sorties aux autres contrôles du fichier XIB, selon les besoins.
    4. Dans SomeView.swift, j’ai chargé XIB dans l’ init ou init:frame: CGRect . Il n’y a pas besoin d’atsortingbuer quoi que ce soit à “soi”. Dès que le XIB est chargé, toutes les sockets sont connectées, y compris la vue de niveau supérieur. La seule chose qui manque, c’est d’append la vue de dessus à la hiérarchie des vues:

       class SomeView: UIView { override init(frame: CGRect) { super.init(frame: frame) NSBundle.mainBundle().loadNibNamed("SomeObject", owner: self, options: nil) self.addSubview(self.view); // adding the top level view to the view hierarchy } required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) NSBundle.mainBundle().loadNibNamed("SomeObject", owner: self, options: nil) self.addSubview(self.view); // adding the top level view to the view hierarchy } ... } 

    Swift 3 version de la réponse de Logan

     extension UIView { public class func fromNib(nibName: Ssortingng? = nil) -> Self { return fromNib(nibName: nibName, type: self) } public class func fromNib(nibName: Ssortingng? = nil, type: T.Type) -> T { return fromNib(nibName: nibName, type: T.self)! } public class func fromNib(nibName: Ssortingng? = nil, type: T.Type) -> T? { var view: T? let name: Ssortingng if let nibName = nibName { name = nibName } else { name = self.nibName } if let nibViews = Bundle.main.loadNibNamed(name, owner: nil, options: nil) { for nibView in nibViews { if let tog = nibView as? T { view = tog } } } return view } public class var nibName: Ssortingng { return "\(self)".components(separatedBy: ".").first ?? "" } public class var nib: UINib? { if let _ = Bundle.main.path(forResource: nibName, ofType: "nib") { return UINib(nibName: nibName, bundle: nil) } else { return nil } } } 
     let subviewArray = NSBundle.mainBundle().loadNibNamed("myXib", owner: self, options: nil) return subviewArray[0] 

    Tout ce que vous avez à faire est d’appeler la méthode init dans votre classe UIView .

    Faites-le de cette façon:

     class className: UIView { @IBOutlet var view: UIView! override init(frame: CGRect) { super.init(frame: frame) setup() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder)! } func setup() { UINib(nibName: "nib", bundle: nil).instantiateWithOwner(self, options: nil) addSubview(view) view.frame = self.bounds } } 

    Maintenant, si vous souhaitez append cette vue en tant que sous-vue dans le contrôleur de vue, procédez comme suit dans le fichier view controller.swift:

     self.view.addSubview(className()) 

    Semblable à certaines des réponses ci-dessus, mais une extension Swift3 UIView plus cohérente:

     extension UIView { class func fromNib (nibName name: Ssortingng, bundle: Bundle? = nil) -> A? { let bundle = bundle ?? Bundle.main let nibViews = bundle.loadNibNamed(name, owner: self, options: nil) return nibViews?.first as? A } class func fromNib() -> T? { return fromNib(nibName: Ssortingng(describing: T.self), bundle: nil) } } 

    Ce qui donne la commodité de pouvoir charger la classe à partir d’une nib nommée, mais également à partir d’autres nibs / bundles.

    Je fais juste comme ça:

     if let myView = UINib.init(nibName: "MyView", bundle: nil).instantiate(withOwner: self)[0] as? MyView { // Do something with myView } 

    Cet exemple utilise la première vue de la nib “MyView.xib” dans le bundle principal. Mais vous pouvez varier soit l’index, le nom de la plume, soit le bundle (principal par défaut).

    J’avais l’habitude de réveiller des vues dans la méthode view init ou de créer des méthodes génériques comme dans les solutions ci-dessus (qui sont intelligentes), mais je ne le fais plus.

    De cette façon, je peux utiliser différentes dispositions ou traits tout en conservant la même logique de vue et le même code.

    Je trouve plus facile de laisser un object fabrique (généralement le viewController qui utilisera la vue) le créer comme il le souhaite. Parfois, vous avez besoin d’un propriétaire (généralement lorsque la vue créée a un sharepoint vente connecté au créateur), parfois pas ..

    C’est probablement pourquoi Apple n’a pas inclus de méthode initFromNib dans sa classe UIView …

    Pour prendre un exemple de base, vous ne savez pas comment vous êtes né. Vous êtes juste né. Ainsi sont les vues;)

    Vous pouvez le faire via le storyboard, ajoutez simplement les contraintes appropriées pour la vue. Vous pouvez le faire facilement en sous- BaseView n’importe quelle vue de votre propre base, disons BaseView :

    Objectif c

     BaseView.h /*! @class BaseView @discussion Base View for getting view from xibFile @availability ios7 and later */ @interface BaseView : UIView @end BaseView.m #import "BaseView.h" @implementation BaseView #pragma mark - Public - (instancetype)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (self) { [self prepareView]; } return self; } #pragma mark - LifeCycle - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self prepareView]; } return self; } #pragma mark - Private - (void)prepareView { NSArray *nibsArray = [[NSBundle mainBundle] loadNibNamed:NSSsortingngFromClass([self class]) owner:self options:nil]; UIView *view = [nibsArray firstObject]; view.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:view]; [self addConstraintsForView:view]; } #pragma mark - Add constraints - (void)addConstraintsForView:(UIView *)view { [self addConstraints:@[[NSLayoutConstraint constraintWithItem:view atsortingbute:NSLayoutAtsortingbuteBottom relatedBy:NSLayoutRelationEqual toItem:self atsortingbute:NSLayoutAtsortingbuteBottom multiplier:1.0 constant:0], [NSLayoutConstraint constraintWithItem:view atsortingbute:NSLayoutAtsortingbuteTop relatedBy:NSLayoutRelationEqual toItem:self atsortingbute:NSLayoutAtsortingbuteTop multiplier:1.0 constant:0], [NSLayoutConstraint constraintWithItem:view atsortingbute:NSLayoutAtsortingbuteLeft relatedBy:NSLayoutRelationEqual toItem:self atsortingbute:NSLayoutAtsortingbuteLeft multiplier:1.0 constant:0], [NSLayoutConstraint constraintWithItem:view atsortingbute:NSLayoutAtsortingbuteRight relatedBy:NSLayoutRelationEqual toItem:self atsortingbute:NSLayoutAtsortingbuteRight multiplier:1.0 constant:0] ]]; } @end 

    Rapide 4

     import UIKit class BaseView : UIView { // MARK: - LifeCycle required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) prepareView() } override init(frame: CGRect) { super.init(frame: frame) prepareView() } internal class func xibName() -> Ssortingng { return Ssortingng(describing: self) } // MARK: - Private fileprivate func prepareView() { let nameForXib = BaseView.xibName() let nibs = Bundle.main.loadNibNamed(nameForXib, owner: self, options: nil) if let view = nibs?.first as? UIView { view.backgroundColor = UIColor.clear view.translatesAutoresizingMaskIntoConstraints = false addSubviewWithConstraints(view, offset: false) } } } UIView+Subview public extension UIView { // MARK: - UIView+Extensions public func addSubviewWithConstraints(_ subview:UIView, offset:Bool = true) { subview.translatesAutoresizingMaskIntoConstraints = false let views = [ "subview" : subview ] addSubview(subview) var constraints = NSLayoutConstraint.constraints(withVisualFormat: offset ? "H:|-[subview]-|" : "H:|[subview]|", options: [.alignAllLeading, .alignAllTrailing], mesortingcs: nil, views: views) constraints.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: offset ? "V:|-[subview]-|" : "V:|[subview]|", options: [.alignAllTop, .alignAllBottom], mesortingcs: nil, views: views)) NSLayoutConstraint.activate(constraints) } } 

    Je propose 2 variantes pour append des contraintes – une commune et dans un langage de format visuel – sélectionnez l’une de vos options 🙂

    En outre, par défaut, le nom de xib a le même nom que celui de la classe d’implémentation. Si non, changez xibName paramètre xibName .

    Si vous sous-classe votre vue depuis BaseView – vous pouvez facilement mettre n’importe quelle vue et spécifier la classe dans IB.

    Version plus puissante basée sur la réponse de Logan

     extension UIView { public class func fromNib(nibName: Ssortingng? = nil) -> Self { return fromNib(nibName: nibName, type: self) } public class func fromNib(nibName: Ssortingng? = nil, type: T.Type) -> T { return fromNib(nibName: nibName, type: T.self)! } public class func fromNib(nibName: Ssortingng? = nil, type: T.Type) -> T? { var view: T? let name: Ssortingng if let nibName = nibName { name = nibName } else { name = self.nibName } if let nibViews = nibBundle.loadNibNamed(name, owner: nil, options: nil) { if nibViews.indices.contains(nibIndex), let tog = nibViews[nibIndex] as? T { view = tog } } return view } public class var nibName: Ssortingng { return "\(self)".components(separatedBy: ".").first ?? "" } public class var nibIndex: Int { return 0 } public class var nibBundle: Bundle { return Bundle.main } } 

    Et vous pouvez utiliser comme

     class BaseView: UIView { override class var nibName: Ssortingng { return "BaseView" } weak var delegate: StandardStateViewDelegate? } class ChildView: BaseView { override class var nibIndex: Int { return 1 } } 

    La mise en œuvre la plus pratique. Ici, vous avez besoin de deux méthodes, afin de retourner directement à l’object de votre classe, pas à UIView.

    1. viewId marqué comme une classe , permettant de le remplacer
    2. Votre fichier .xib peut contenir plusieurs vues du niveau supérieur, cette situation est également gérée correctement.

     extension UIView { class var viewId: Ssortingng { return Ssortingng(describing: self) } static func instance(from bundle: Bundle? = nil, nibName: Ssortingng? = nil, owner: Any? = nil, options: [AnyHashable : Any]? = nil) -> Self? { return instancePrivate(from: bundle ?? Bundle.main, nibName: nibName ?? viewId, owner: owner, options: options) } private static func instancePrivate(from bundle: Bundle, nibName: Ssortingng, owner: Any?, options: [AnyHashable : Any]?) -> T? { guard let views = bundle.loadNibNamed(nibName, owner: owner, options: options), let view = views.first(where: { $0 is T }) as? T else { return nil } return view } } 

    Exemple:

     guard let customView = CustomView.instance() else { return } //Here customView has CustomView class type, not UIView. print(customView is CustomView) // true 

    Si vous souhaitez que la sous-classe Swift UIView soit entièrement autonome et puisse être instanciée à l’aide d’init ou init (frame 🙂 sans exposer les détails de l’implémentation de l’utilisation d’un Nib, vous pouvez utiliser une extension de protocole pour y parvenir. Cette solution évite la hiérarchie UIView nestede, comme le suggèrent de nombreuses autres solutions.

     public class CustomView: UIView { @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var valueLabel: UILabel! public convenience init() { self.init(frame: CGRect.zero) } public override convenience init(frame: CGRect) { self.init(internal: nil) self.frame = frame } public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) commonInit() } fileprivate func commonInit() { } } fileprivate protocol _CustomView { } extension CustomView: _CustomView { } fileprivate extension _CustomView { // Protocol extension initializer - has the ability to assign to self, unlike // class initializers. Note that the name of this initializer can be anything // you like, here we've called it init(internal:) init(internal: Int?) { self = Bundle.main.loadNibNamed("CustomView", owner:nil, options:nil)![0] as! Self; } } 
     class func loadFromNib() -> T { let nibName = Ssortingng(describing: self) return Bundle.main.loadNibNamed(nibName, owner: nil, options: nil)![0] as! T } 

    Rapide 4

    N’oubliez pas d’écrire “d’abord comme? CustomView”.

     if let customView = Bundle.main.loadNibNamed("myXib", owner: self, options: nil)?.first as? CustomView { self.view.addSubview(customView) } 

    Si vous voulez utiliser n’importe où

    La meilleure solution est la réponse de Robert Gummesson .

     extension UIView { class func fromNib() -> T { return Bundle.main.loadNibNamed(Ssortingng(describing: T.self), owner: nil, options: nil)![0] as! T } } 

    Alors appelez comme ceci:

     let myCustomView: CustomView = UIView.fromNib() 

    Voici un moyen propre et déclaratif de charger par programmation une vue en utilisant une extension de protocole et de protocole (Swift 4.1):

     protocol XibLoadable { associatedtype CustomViewType static func loadFromXib() -> CustomViewType } extension XibLoadable where Self: UIView { static func loadFromXib() -> Self { let nib = UINib(nibName: "\(self)", bundle: Bundle.main) guard let customView = nib.instantiate(withOwner: self, options: nil).first as? Self else { // your app should crash if the xib doesn't exist preconditionFailure("Couldn't load xib for view: \(self)") } return customView } } 

    Et vous pouvez l’utiliser comme ça:

     // don't forget you need a xib file too final class MyView: UIView, XibLoadable { ... } // and when you want to use it let viewInstance = MyView.loadFromXib() 

    Quelques considérations supplémentaires :

    1. Assurez-vous que le fichier xib de votre vue personnalisée contient l’ensemble de Custom Class la vue (ainsi que l’ensemble des sorties / actions à partir de là), et non celui du propriétaire du fichier.
    2. Vous pouvez utiliser ce protocole / cette extension externe à votre vue personnalisée ou interne. Vous souhaiterez peut-être l’utiliser en interne si vous avez d’autres tâches à effectuer lors de l’initialisation de votre vue.
    3. Votre classe de vue personnalisée et votre fichier xib doivent avoir le même nom.