如何在Swift中用XIB文件初始化/实例化一个自定义的UIView类

我有一个名为MyClass的类,它是UIView的子类,我想用XIB文件初始化。 我不知道如何使用名为View.xib的xib文件来初始化这个类

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

我testing了这个代码,它效果很好

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

初始化视图并像下面一样使用它

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

要么

  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 } 

从Swift 2.0开始,你可以添加一个协议扩展。 在我看来,这是一个更好的方法,因为返回types是Self而不是UIView ,所以调用者不需要转换到视图类。

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

山姆的解决scheme已经很好,尽pipe它没有考虑到不同的捆绑(NSBundle:forClass来救援),并需要手动加载,也就是打字代码。

如果你想完全支持你的Xibsockets,不同的Bundles(在框架中使用!),并在Storyboard中获得一个不错的预览试试这个:

 // 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: String(self.dynamicType), bundle: bundle) let nibView = nib.instantiateWithOwner(self, options: nil).first as! UIView return nibView } } 

像往常一样使用你的xib,即连接出口文件所有者和设置文件所有者类到你自己的类。

用法:从NibLoadingView子类化你自己的View类。

没有额外的代码需要了。

信用到期的信用:与GH的DenHeadless稍微改变分开。 我的要点: https : //gist.github.com/winkelsdorf/16c481f274134718946328b6e2c9a4d8

这就是弗雷德里克在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: String(describing: type(of: self)), bundle: bundle) let nibView = nib.instantiate(withOwner: self, options: nil).first as! UIView return nibView } } 

从xib加载视图的通用方式:

例:

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

执行:

 extension Bundle { static func loadView<T>(fromNib name: String, 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 " + String(describing: type)) } } 

Swift 3答案:就我而言,我想在我的自定义类中有一个可修改的sockets:

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

在.xib中时,请确保自定义类字段是MyClassView。 不要打扰文件的所有者。

确保自定义类是MyClassView

另外,请确保您将MyClassView中的sockets连接到标签: 为myLabel出口

要实例化它:

 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:String , string : String ){ lblTital.text = title txtView.text = string 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) }) }) }