2016-02-26 23 views
11

Sto tentando di caricare il file XIB in un UIView ma ho qualche problema. Ho le funzioni di override richieste ma sembrano bloccarsi. Dicendo questo errore, avviso:Caricamento di un file XIB su UIView Swift

Impossibile caricare qualsiasi informazione di classe Objective-C. Questo sarà ridurre significativamente la qualità delle informazioni sul tipo disponibili.

Mi chiedevo se qualcuno potesse dimostrare come caricare correttamente il file XIB in un UIView

import UIKit 

class Widget: UIView { 

    let view = UIView() 

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

     //call function 

     loadNib() 

    } 

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

     loadNib() 

     //fatalError("init(coder:) has not been implemented") 
    } 

    func loadNib() { 
     let bundle = NSBundle(forClass: self.dynamicType) 
     let nib = UINib(nibName: "nib", bundle: bundle) 
     let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView 
     view.frame = bounds 
     view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] 
     self.addSubview(view); 
    } 
} 
+0

è il file XIB davvero chiamato "zero"? – lukaivicev

+0

Sì, è chiamato pennino –

+0

Sembra funzionare bene ... quale linea specifica si blocca? –

risposta

27

io li utilizza in uno dei nostri progetti, maby suo utile a voi

import UIKit 

class RegisterPageView: UIView { 

     class func instanceFromNib() -> RegisterPageView { 
      return UINib(nibName: "RegisterPageView", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! RegisterPageView 
     } 
} 
+0

Non funziona con 'thisView.alpha = 0',' thisView.superview' – Jack

3

solito utilizzare il seguente modo per caricare un file XI ter di proprietà di una consuetudine UIView:

NSBundle.mainBundle().loadNibNamed(nibName, owner: self, options: nil)[0]; 
+1

Non ha funzionato. Ancora lo stesso errore –

1
let xibView = NSBundle.mainBundle().loadNibNamed("NameXibView", owner: nil, options: nil)[0] as! UIView 
13

Utilizzando Swift 3,0

let viewFromNib: UIView? = Bundle.main.loadNibNamed("NibName", 
    owner: nil, 
    options: nil)?.first 
6

per rapida 3

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

Puoi riempire alcuni spazi in più? Dove va e dove viene chiamato? Ho continuato a farlo più a lungo di quanto ammetto di ammettere e tutto ciò che ho trovato non è aggiornato né Swift né Objective-C. Sembra che sia un semplice esercizio, ma sono troppo stupido per capirlo. – Adrian

2

Nel mio progetto ho realizzato le seguenti (molto simile alla soluzione di Peter)

import UIKit 

// MARK: - Protocol Declaration 

public protocol InterfaceBuilderInstantiable 
{ 
    /// The UINib that contains the view 
    /// 
    /// Defaults to the swift class name if not implemented 
    static var associatedNib : UINib { get } 
} 

// MARK: - Default Implementation 

extension InterfaceBuilderInstantiable 
{ 
    /// Creates a new instance from the associated Xib 
    /// 
    /// - Returns: A new instance of this object loaded from xib 
    static func instantiateFromInterfaceBuilder() -> Self 
    { 
     return associatedNib.instantiate(withOwner:nil, options: nil)[0] as! Self 
    } 

    static var associatedNib : UINib 
    { 
     let name = String(describing: self) 
     return UINib(nibName: name, bundle: Bundle.main) 
    } 
} 

Per utilizzare, basta semplicemente implementare il protocollo:

class MyView: UIView, InterfaceBuilderInstantiable 
{ 
    // The rest 

E se il pennino è lo stesso nome la classe (MyView.xib), il gioco è fatto: l'implementazione predefinita del protocollo cerca un pennino con il lo stesso nome della classe nel pacchetto principale.

Ovviamente, se il pennino si trova in un altro pacchetto o ha un nome diverso, è possibile ignorare lo associatedNib e restituire il proprio pennino.

11

Ecco il mio approccio (scritto in Swift 3.1):

protocol XibDesignable : class {} 

extension XibDesignable where Self : UIView { 

    static func instantiateFromXib() -> Self { 

     let dynamicMetatype = Self.self 
     let bundle = Bundle(for: dynamicMetatype) 
     let nib = UINib(nibName: "\(dynamicMetatype)", bundle: bundle) 

     guard let view = nib.instantiate(withOwner: nil, options: nil).first as? Self else { 

      fatalError("Could not load view from nib file.") 
     } 
     return view 
    } 
} 

extension UIView : XibDesignable {} 

Ora ho semplicemente possibile creare qualsiasi sottoclasse UIView da un Xib (ammesso che ve ne sia uno) in questo modo MyCustomView.instantiateFromXib(). Ricordarsi di denominare il file Xib esattamente come sottoclasse UIView e impostare correttamente il tipo di vista principale in tale file Xib.


Appena sarà attuato SR-0068 si potrebbe cadere il protocollo e spostare la funzione direttamente nell'estensione UIView.


Solo una nota: il post originale utilizza uno schema di uso comune con una vista nidificata. IMHO questo è uno schema errato che non utilizza le risorse e crea solo una gerarchia di viste non necessaria.

+0

Mi piace questo approccio. Nel mio caso, i file .xib contengono solo una vista della classe corrente e 'guard let view = nib.instantiate (withOwner: nil, options: nil) .last' crashed, poiché' .last' ha restituito nil. Per qualche ragione, 'guard lascia view = nib.intesticare (withOwner: nil, options: nil) [0]' funziona benissimo però. Basta cambiare '.last' a' [0] ' –

+1

Non c'è' .last' nel mio esempio. Inoltre '.first' non può essere nullo se l'array contiene veramente qualcosa. '[0]' si bloccherà anche se la matrice è vuota. – DevAndArtist

8

migliorata DevAndArtist estensione UIView

public extension UIView 
{ 
    static func loadFromXib<T>(withOwner: Any? = nil, options: [AnyHashable : Any]? = nil) -> T where T: UIView 
    { 
     let bundle = Bundle(for: self) 
     let nib = UINib(nibName: "\(self)", bundle: bundle) 

     guard let view = nib.instantiate(withOwner: withOwner, options: options).first as? T else { 
      fatalError("Could not load view from nib file.") 
     } 
     return view 
    } 
} 

Uso

let view = CustomView.loadFromXib() 
let view = CustomView.loadFromXib(withOwner: self) 
let view = CustomView.loadFromXib(withOwner: self, options: [UINibExternalObjects: objects]) 

External Objects discussion

2

Swift 4.x

let myView = Bundle.main.loadNibNamed("yourXibView", owner: nil, options: nil)![0] as! UIView 
-1
func configureNib() -> UIView { 
    let bundle = Bundle(for: type(of: self)) 
    let nib = UINib(nibName: "CustomUIView", bundle: bundle) 
    let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView 
    return view 
} 

E utilizzare questo tutorial per visualizzazione personalizzata con XI ter ... https://developerfly.com/custom-view-use-xib-swift/

+0

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - [Dalla recensione] (/ recensione/post di bassa qualità/17918412) –

Problemi correlati