我正在尝试将XIB
文件加载到UIView
但我遇到了一些麻烦。我有所需的覆盖功能,但它们似乎崩溃了。说出这个错误,警告:
无法加载任何Objective-C类信息。这将 显着降低了可用类型信息的质量。
我想知道是否有人可以告诉我如何将XIB
文件正确加载到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 :(得分:39)
我在我们的一个项目中使用它,maby对你很有用
import UIKit
class RegisterPageView: UIView {
class func instanceFromNib() -> RegisterPageView {
return UINib(nibName: "RegisterPageView", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! RegisterPageView
}
}
答案 1 :(得分:18)
使用Swift 3.0
let viewFromNib: UIView? = Bundle.main.loadNibNamed("NibName",
owner: nil,
options: nil)?.first
答案 2 :(得分:13)
这是我的方法(用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 {}
现在我只需要从Xib(假设有一个)创建任何UIView子类,就像MyCustomView.instantiateFromXib()
一样。请记住将您的Xib文件命名为UIView
子类,并正确设置该Xib文件中主视图的类型。
只要SE-0068实施,就可以删除协议并将功能直接移至UIView
扩展名。
只是注意:原始帖子使用具有嵌套视图的常用模式。恕我直言这是一个糟糕的模式,它不利用资源,只创建不必要的视图层次结构。
答案 3 :(得分:12)
改进了DevAndArtist 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
}
}
用法
let view = CustomView.loadFromXib()
let view = CustomView.loadFromXib(withOwner: self)
let view = CustomView.loadFromXib(withOwner: self, options: [UINibExternalObjects: objects])
答案 4 :(得分:7)
Swift 4.x
let myView = Bundle.main.loadNibNamed("yourXibView", owner: nil, options: nil)![0] as! UIView
答案 5 :(得分:6)
swift 3
class YourClass: UIView {
class func instanceFromNib() -> YourClass {
return UINib(nibName: "YourClassNibName", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! YourClass
}
}
答案 6 :(得分:4)
在我的项目中,我实现了以下内容(非常类似于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)
}
}
要使用,您只需实施协议:
class MyView: UIView, InterfaceBuilderInstantiable
{
// The rest
如果您的笔尖与您的类(MyView.xib
)同名,则您需要设置:协议的默认实现查找与主包中的类同名的笔尖
当然,如果您的笔尖在另一个包中或者名称不同,您可以覆盖associatedNib
并返回自己的笔尖。
答案 7 :(得分:3)
通常我使用以下方式加载自定义UIView
所拥有的xib文件:
NSBundle.mainBundle().loadNibNamed(nibName, owner: self, options: nil)[0];
答案 8 :(得分:1)
let xibView = NSBundle.mainBundle().loadNibNamed("NameXibView", owner: nil, options: nil)[0] as! UIView
答案 9 :(得分:0)
Swift 4.x
我终于做到了 这不在customView本身中。我将代码放在ViewController加载customView的位置。
import UIKit
class StartMenuViewController: UIViewController {
@IBOutlet weak var customView: CustomView!
override func viewDidLoad() {
super.viewDidLoad()
let myView = Bundle.main.loadNibNamed("CustomView", owner: self, options: nil)![0] as! UIView
customView .addSubview(myView)
}
答案 10 :(得分:0)
我想分享这段代码,这需要我付出一些努力才能使其具有弹性。
import Foundation
protocol Nib {
func registerNib()
}
extension Nib where Self : UIView {
func registerNib() {
guard let nibName = type(of: self).description().components(separatedBy: ".").last else { return }
// ** Check if resource is used in Interface Builder first to avoid crash during compile
#if !TARGET_INTERFACE_BUILDER
let bundle = Bundle(for: type(of: self))
guard let _ = bundle.path(forResource: nibName, ofType: "nib")
else { fatalError("can't find \(nibName) xib resource in current bundle") }
#endif
guard let view = Bundle(for: type(of: self)).loadNibNamed(nibName, owner: self, options: nil)?.first as? UIView
else { return }
// ** Another way to write it but do not work if xib is bundled with framework
//guard let view = UINib(nibName: nibName, bundle: nil).instantiate(withOwner: self, options: nil).first as? UIView
// else { return }
view.frame = bounds
addSubview(view)
}
}
您可以按照以下步骤使用它来创建名为类名(也称为CustomView.xib)的xib资源文件
import UIKit
class CustomView: UIView, Nib {
override init(frame: CGRect) {
super.init(frame: frame)
postInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
postInit()
}
func postInit() {
registerNib()
}
}
不要忘记将xib资源文件的所有者类设置为CustomView,并保留空白的自定义类类字段。
答案 11 :(得分:0)
Swift 5.x
let loadMusicView = Bundle.main.loadNibNamed("MusicView", owner: nil, options: nil)![0] as? MusicView
loadMusicView?.frame = controlsMainView.bounds
loadMusicView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
controlsMainView.addSubview(loadMusicView!)
//if you have variables in your .xib file access those variables like this
loadMusicView.yourVariableName = .....
答案 12 :(得分:0)
//**只需使用这个类作为视图的超类**
import UIKit
class ViewWithXib: UIView {
func initUI() {}
private func xibSetup() {
let view = loadViewFromNib()
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
addSubview(view)
initUI()
}
private func loadViewFromNib() -> UIView {
let thisName = String(describing: type(of: self))
let view = Bundle(for: self.classForCoder).loadNibNamed(thisName, owner: self, options: nil)?.first as! UIView
return view
}
override init(frame: CGRect) {
super.init(frame: frame)
xibSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibSetup()
}
}
// 用法
class HeaderView: ViewWithXib {
}
let header = HeaderView() // No need to load the view from nib, It will work
答案 13 :(得分:-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
}
使用本教程进行xib自定义视图... https://developerfly.com/custom-view-use-xib-swift/