Swift 3 加载 xib。 NSBundle.mainBundle().loadNibNamed return 布尔

Swift 3 Load xib. NSBundle.mainBundle().loadNibNamed return Bool

我试图找出如何使用 xib 文件创建自定义视图。 在此question中使用了下一个方法。

NSBundle.mainBundle().loadNibNamed("CardView", owner: nil, options: nil)[0] as! UIView

Cocoa也有同样的方法,但是这个方法在swift3中变成了loadNibNamed(_:owner:topLevelObjects:),即returns Bool,前面的代码生成 "Type Bool has no subscript members" 错误,这是显而易见的,因为 return 类型是 Bool。

所以,我的问题是如何从 Swift 3

中的 xib 文件加载视图

首先Swift3.

中的方法没有改变

loadNibNamed(_:owner:topLevelObjects:) 已在 macOS 10.8 中引入,并出现在 Swift 的所有版本中。但是 loadNibNamed(nibName:owner:options:) 已在 Swift 3.

中删除

方法的签名是

func loadNibNamed(_ nibName: String, 
                      owner: Any?, 
            topLevelObjects: AutoreleasingUnsafeMutablePointer<NSArray>?) -> Bool

所以你必须创建一个指针来获取 return 上的视图数组。

var topLevelObjects = NSArray()
if Bundle.main.loadNibNamed("CardView", owner: self, topLevelObjects: &topLevelObjects) {
   let views = (topLevelObjects as Array).filter { [=11=] is NSView }
   return views[0] as! NSView
}

编辑:我更新了答案以可靠地过滤 NSView 实例。


Swift 4 中,语法略有变化,使用 first(where 效率更高:

var topLevelObjects : NSArray?
if Bundle.main.loadNibNamed(assistantNib, owner: self, topLevelObjects: &topLevelObjects) {
     return topLevelObjects!.first(where: { [=12=] is NSView }) as? NSView
}

Swift 4 @vadian 回答的版本

var topLevelObjects: NSArray?
if Bundle.main.loadNibNamed(NSNib.Name(rawValue: nibName), owner: self, topLevelObjects: &topLevelObjects) {
    return topLevelObjects?.first(where: { [=10=] is NSView } ) as? NSView
}

我写了一个安全的扩展,可以很容易地从 nib 加载:

extension NSView {
    class func fromNib<T: NSView>() -> T? {
        var viewArray = NSArray()
        guard Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, topLevelObjects: &viewArray) else {
            return nil
        }
        return viewArray.first(where: { [=10=] is T }) as? T
    }
}

那么就这样使用:

let view: CustomView = .fromNib()

CustomView是否是NSView的子类并且CustomView.xib.