我有一个名为MyClass
的类,它是UIView
的子类,我想用XIB
文件进行初始化。我不确定如何使用名为View.xib
class MyClass: UIView {
// what should I do here?
//init(coder aDecoder: NSCoder) {} ??
}
答案 0 :(得分:236)
我测试了这段代码,效果很好
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())
UPDATE Swift> = 3.x& Swift> = 4.x
class func instanceFromNib() -> UIView {
return UINib(nibName: "nib file name", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! UIView
}
答案 1 :(得分:77)
Sam的解决方案已经很好了,尽管它没有考虑不同的捆绑(NSBundle:forClass来救援)并且需要手动加载,a.k.a打字代码。
如果你想完全支持你的Xib Outlets,不同的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,即将Outlets连接到File Owner并将File Owner类设置为你自己的类。
用法:只需从NibLoadingView继承自己的View类。
不再需要其他代码。
信用额到期的信用:在DenHeadless对GH的微小变化中加以分析。我的要点:https://gist.github.com/winkelsdorf/16c481f274134718946328b6e2c9a4d8
答案 2 :(得分:73)
从Swift 2.0开始,您可以添加协议扩展。在我看来,这是一种更好的方法,因为返回类型是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
}
}
答案 3 :(得分:35)
这就是Frederik在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
}
}
答案 4 :(得分:30)
Universal way of loading view from xib:
Example:
let myView = Bundle.loadView(fromNib: "MyView", withType: MyView.self)
Implementation:
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))
}
}
答案 5 :(得分:26)
Swift 3答案:就我而言,我想在我的自定义课程中设置一个我可以修改的插座:
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中,确保Custom Class字段为MyClassView。不要为File的所有者烦恼。
要实例化它:
let myClassView = MyClassView.createMyClassView()
myClassView.myLabel.text = "Hello World!"
答案 6 :(得分:14)
快捷键4
在这种情况下,我必须将数据传递到该自定义视图中,因此我创建了静态函数来实例化该视图。
创建UIView扩展
extension UIView {
class func initFromNib<T: UIView>() -> T {
return Bundle.main.loadNibNamed(String(describing: self), owner: nil, options: nil)?[0] as! T
}
}
创建MyCustomView
class MyCustomView: UIView {
@IBOutlet weak var messageLabel: UILabel!
static func instantiate(message: String) -> MyCustomView {
let view: MyCustomView = initFromNib()
view.messageLabel.text = message
return view
}
}
实例化视图
let view = MyCustomView.instantiate(message: "Hello World.")
答案 7 :(得分:3)
有一些框架实现了在此页面上多次提到的相同代码。
我正在发布其中一个框架LoadableViews。
由于这个框架已经在MLSDev的几乎所有应用程序中使用,我正在研究的公司,它将在可预见的未来得到积极支持。
只需在此处发帖给任何感兴趣的人。
答案 8 :(得分:2)
Swift 5.2
创建一个名为 import Foundation
import UIKit
/* Usage:
- Subclass your UIView from NibLoadView to automatically load an Xib with the same name as your class
- Set the class name to File's Owner in the Xib file
*/
@IBDesignable
class NibLoadingView: UIView {
@IBOutlet weak var view: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
nibSetup()
}
override func awakeFromNib() {
super.awakeFromNib()
nibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
nibSetup()
}
private func nibSetup() {
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: type(of: self).description().replacingOccurrences(of: "REPLACEME.", with: ""), bundle: bundle)
let nibView = nib.instantiate(withOwner: self, options: nil).first as! UIView
return nibView
}
}
的类,内容如下:
REPLACEME
在上面的代码中找到 NibLoadingView
并将其替换为您的项目名称。
现在创建一个 XIB 和 UIView 类对,将 XIB 的所有者设置为 UIView 类和子类 ExampleView()
。
您现在可以像 ExampleView(frame: CGRect)
、{{1}} 等一样初始化类
答案 9 :(得分:1)
如果有人想以编程方式使用XIB加载自定义视图,则下面的代码将起作用。
let customView = UINib(nibName:"CustomView",bundle:.main).instantiate(withOwner: nil, options: nil).first as! UIView
customView.frame = self.view.bounds
self.view.addSubview(customView)
答案 10 :(得分:-2)
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)
})
})
}