【问题标题】:Swift 3 Load xib. NSBundle.mainBundle().loadNibNamed return BoolSwift 3 加载 xib。 NSBundle.mainBundle().loadNibNamed 返回布尔值
【发布时间】:2017-03-27 00:50:55
【问题描述】:

我试图弄清楚如何使用 xib 文件创建自定义视图。 在这个question 中使用了下一个方法。

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

Cocoa也有同样的方法,不过这个方法在swift 3中改成了loadNibNamed(_:owner:topLevelObjects:)返回 Bool,之前的代码生成"Type Bool has no subscript members"错误,很明显,因为返回类型是Bool。

所以,我的问题是如何在 Swift 3 中从 xib 文件加载视图

【问题讨论】:

    标签: cocoa swift3 xib nsview nib


    【解决方案1】:

    首先Swift 3中没有改变方法。

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

    方法的签名是

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

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

    var topLevelObjects = NSArray()
    if Bundle.main.loadNibNamed("CardView", owner: self, topLevelObjects: &topLevelObjects) {
       let views = (topLevelObjects as Array).filter { $0 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: { $0 is NSView }) as? NSView
    }
    

    【讨论】:

    • 一行让view = topLevelObjects[0] as! NSView - 我收到一个错误“无法将 'NSApplication' (0x7fffd8201278) 类型的值转换为 'NSView' (0x7fffd8210048)。”
    • 调用此方法假定存在一个包含视图作为顶级对象的 nib/xib 文件。
    • 谢谢,发现一个错误。
    • 小错字:toplevelObjects。和 assistantNib 没有定义。请参阅 Ryan 的回答,了解如何定义。
    【解决方案2】:

    Swift 4 版本的@vadian 的回答

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

    【讨论】:

      【解决方案3】:

      我写了一个安全的扩展,可以很容易地从 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: { $0 is T }) as? T
          }
      }
      

      然后像这样使用:

      let view: CustomView = .fromNib()
      

      CustomView 是否是 NSView 的子类以及 CustomView.xib

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-11-24
        • 2015-09-23
        • 2013-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-08
        相关资源
        最近更新 更多