webentwicklung-frage-antwort-db.com.de

Weisen Sie der UIView in Swift Xib zu

in Objective C kann dies in der init-Methode durch durchgeführt werden

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

aber wenn ich das in Swift mache

init(frame: CGRect) {
    self = NSBundle.mainBundle().loadNibNamed("ViewDetailMenu", owner: 0, options: nil)[0] as? UIView
}

selbst in einer Methode kann kein Fehler zugewiesen werden . Nun ist es mein Ansatz, eine Ansicht zu erstellen und die von der Feder geladene Ansicht hinzuzufügen Hat jemand eine bessere Idee?

56
Siu Chung Chan

für Swift 4

extension UIView {
    class func loadFromNibNamed(nibNamed: String, bundle: Bundle? = nil) -> UIView? {
      return UINib(
          nibName: nibNamed,
          bundle: bundle
      ).instantiate(withOwner: nil, options: nil)[0] as? UIView
  }
}

für Swift 3

Sie können eine Erweiterung in UIView erstellen:

extension UIView {
    class func loadFromNibNamed(nibNamed: String, bundle: NSBundle? = nil) -> UIView? {
        return UINib(
            nibName: nibNamed,
            bundle: bundle
        ).instantiateWithOwner(nil, options: nil)[0] as? UIView
    }
}

Hinweis : Die Verwendung von UINib ist schneller, da die Zwischenspeicherung für Sie erfolgt.

Dann können Sie einfach folgendes tun:

ViewDetailItem.loadFromNibNamed("ViewBtnWishList")

Und Sie können diese Methode in jeder Ansicht wiederverwenden.

123
drewag

Getestet in Xcode 7 Beta 4, Swift 2.0. Der folgende Code weist der UIView..__ xib zu. Sie können diese benutzerdefinierte xib-Ansicht im Storyboard verwenden und auch auf das Objekt IBOutlet zugreifen.

import UIKit

@IBDesignable class SimpleCustomView:UIView
{
    var view:UIView!;

    @IBOutlet weak var lblTitle: UILabel!

   @IBInspectable var lblTitleText : String?
        {
        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);



    }


}

Greifen Sie programmgesteuert auf customview zu

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

Quellcode - https://github.com/karthikprabhuA/CustomXIBSwift

23

Das hat bei mir funktioniert. 

override func awakeAfterUsingCoder(aDecoder: NSCoder) -> AnyObject? {
    if self.subviews.count == 0 {
        return loadNib()
    }
    return self
}

private func loadNib() -> YourCustomView {
    return NSBundle.mainBundle().loadNibNamed("YourCustomViewNibName", owner: nil, options: nil)[0] as YourCustomView
}
22
Dave

das könnte eine Lösung für Sie sein:

Swift 3.x

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

Swift 2.x

class func instanceFromNib() -> UIView {
    return UINib(nibName: "<<NibFileName>>", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as UIView
}
16
holex

Ich denke, dies ist der einfachste, aber auch sauberste Weg, einem UIView ein Xib zuzuweisen. Xcode 7.3 und Swift 2.0.

import UIKit

//Create CustomView class
class CustomView: UIView {

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

//Use it
let customView = CustomView.instanceFromNib() as! CustomView
3
rilar

Der wahre schnelle Ansatz ist die Verwendung von Protokollen und Protokollerweiterungen.

Ich benutze es so: Zu Beginn erstelle ich ein Protokoll

    protocol XibInitializable {
        static var name: String { get }
        static var bundle: Bundle? { get }

        static func fromXib() -> Self
    }

dann mache ich eine Standardimplementierung dieses Protokolls mit Protokollerweiterung

extension XibInitializable where Self : UIView {
    static var name: String {
        return String(describing: Self.self)
    }

    static var bundle: Bundle? {
        return nil
    }

    static func fromXib() -> Self {
        return UINib(nibName: name, bundle: bundle).instantiate(withOwner: nil, options: nil)[0] as! Self
    }
}

die Implementierung unseres Protokolls ist nun abgeschlossen

Damit dieses Protokoll funktioniert, müssen der Name unserer xib-Datei und die Klasse identisch sein. Zum Beispiel zum Beispiel

enter image description here

füge das Protokoll hinzu und mache deine Klasse " final ", wie hier.

enter image description here

Das war's

und verwenden

enter image description here

1
Beslan Tularov

anstatt eine Erweiterung zu UIView hinzuzufügen, können Sie ein Protokoll definieren und die Implementierung zu einer Protokollerweiterung hinzufügen. Sie können dann erklären, dass UIView dem Protokoll entspricht.

Dadurch kann der Rückgabetyp Self anstelle von UIView sein. Der Anrufer muss also nicht in die Klasse wechseln.

Hier erklärt: https://stackoverflow.com/a/33424509/845027

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(String.init).last!
    let nib = UINib(nibName: nibName, bundle: nil)
    return nib.instantiateWithOwner(self, options: nil).first as! Self
  }

}
0
Sam

Sie haben gerade eine Erweiterung UINib erstellt, um eine Ansicht aus Xib zu laden und mithilfe von Einschränkungen, Generics und starken Namen in eine Containeransicht einzubetten (ohne Strings zu verwenden, vorausgesetzt, Sie haben denselben Dateinamen für Xib und Implementierung):

extension UINib {

    static func instantiateViewAndEmbedWithConstraints <T: UIView> (viewType viewType: T.Type, embedInto containerView: UIView) -> T {
        let view = UINib(nibName: String(viewType), bundle: nil).instantiateWithOwner(nil, options: nil).first as! T
        containerView.addSubview(view)
        view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint(item: view, attribute: .Leading, relatedBy: .Equal, toItem: containerView, attribute: .Leading, multiplier: 1, constant: 0).active = true
        NSLayoutConstraint(item: view, attribute: .Trailing, relatedBy: .Equal, toItem: containerView, attribute: .Trailing, multiplier: 1, constant: 0).active = true
        NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal, toItem: containerView, attribute: .Top, multiplier: 1, constant: 0).active = true
        NSLayoutConstraint(item: view, attribute: .Bottom, relatedBy: .Equal, toItem: containerView, attribute: .Bottom, multiplier: 1, constant: 0).active = true
        return view
    }

}

Verwendungszweck:

...outlets...
@IBOutlet var containerView: UIView!
var customView: CustomView!

...viewDidLoad...
customView = UINib.instantiateViewAndEmbedWithConstraints(viewType: CustomView.self, embedInto: containerView)
0
rshev