2016-02-26 11 views
11

Próbuję załadować mój plik XIB do UIView, ale mam pewne problemy. Mam wymagane funkcje zastępowania, ale wydaje się, że ulegają awarii. Mówiąc ten błąd, ostrzeżenie:Ładowanie pliku XIB do UIView Swift

nie można załadować informacji o klasie Celive-C. To spowoduje, że znacząco obniży jakość dostępnych informacji o typie.

Zastanawiałem się, czy ktoś może mi pokazać jak prawidłowo załadować plik XIB w 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

Czy Twój plik XIB naprawdę o nazwie „zero”? – lukaivicev

+0

Tak, nazywa się stalówka –

+0

Wydaje się działać dobrze ... Która konkretna linia się zawiesza? –

Odpowiedz

27

Używam tego w jednym z naszych projektów, maby mu się przydać

import UIKit 

class RegisterPageView: UIView { 

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

Nie działa z 'thisView.alpha = 0',' thisView.superview' – Jack

3

Zwykle używam następujący sposób załadować plik XIB posiadanych przez zwyczaju UIView:

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

To nie zadziałało. Wciąż ten sam błąd –

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

Korzystanie Swift 3.0

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

dla Swift 3

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

Czy możesz wypełnić więcej pustych miejsc? Gdzie to się dzieje i gdzie się nazywa? Grzewałam z tym dłużej, niż chciałbym przyznać i wszystko, co znalazłem, jest albo przestarzałe Swift albo Objective-C. Wydaje się, że to proste ćwiczenie, ale jestem zbyt głupi, żeby to rozgryźć. – Adrian

2

w moim projekcie I wdrożone następujące (bardzo podobny do rozwiązania Piotra)

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) 
    } 
} 

Aby skorzystać, wystarczy po prostu wdrożyć protokół:

class MyView: UIView, InterfaceBuilderInstantiable 
{ 
    // The rest 

A jeśli stalówka jest taka sama jak nazwa klasy (MyView.xib), jesteś ustawiony: domyślna implementacja protokołu wygląda na stalówki z tak samo jak klasa w głównym pakiecie.

Oczywiście, jeśli stalówka jest w innym pakunku lub ma inną nazwę, można zastąpić associatedNib i zwrócić własną stalówkę.

11

Oto moje podejście (napisany w 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 {} 

teraz po prostu może utworzyć dowolną podklasy UIView od A XIb (zakładając, że jest) Podobnie jak MyCustomView.instantiateFromXib(). Pamiętaj, aby nazwać swój plik Xib dokładnie tak, jak podklasę UIView i poprawnie ustawić typ widoku głównego w tym pliku Xib.


Jak tylko SR-0068 realizowany będzie można upuścić protokół i przejść bezpośrednio do funkcji rozszerzenia UIView.


Tylko uwaga: Oryginalny wpis wykorzystuje powszechnie używany wzorzec z widokiem zagnieżdżonym. IMHO to zły wzór, który nie wykorzystuje zasobów i tworzy tylko niepotrzebną hierarchię widoków.

+0

Podoba mi się to podejście. W moim przypadku pliki .xib zawierają tylko jeden widok bieżącej klasy i 'guard let view = nib.instantiate (withOwner: nil, options: nil) .last' uległo awarii, ponieważ' .last' zwróciło zero. Z jakiegoś powodu, 'guard let view = nib.instantiate (withOwner: nil, options: nil) [0]' działa świetnie. Wystarczy zmienić '.last' na' [0] ' –

+1

Nie ma' .last' w mojej próbce. Ponadto '.first' nie może być zerowe, jeśli tablica naprawdę zawiera coś. '[0]' również się zawiesi, jeśli tablica jest pusta. – DevAndArtist

8

Lepsza DevAndArtist przedłużenie 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 
    } 
} 

Wykorzystanie

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 
} 

i wykorzystują to poradnik dla niestandardowego widoku XIb ... https://developerfly.com/custom-view-use-xib-swift/

+0

Podczas gdy ten link może odpowiedzieć na pytanie, lepiej umieścić tutaj istotne części odpowiedzi i podać link do odsyłacza. Odpowiedzi dotyczące linków mogą stać się nieprawidłowe, jeśli strona z linkami się zmieni. - [Z recenzji] (/ opinia/niskiej jakości-posts/17918412) –

Powiązane problemy