Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I was trying to figure out how to create a custom view using xib files. In this question the next method is used.

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

Cocoa has the same method,however, this method has changed in swift 3 to loadNibNamed(_:owner:topLevelObjects:), which returns Bool, and previous code generates "Type Bool has no subscript members" error, which is obvious, since the return type is Bool.

So, my question is how to a load view from xib file in Swift 3

like image 345
Alexei Avatar asked Nov 13 '16 05:11

Alexei


Video Answer


2 Answers

First of all the method has not been changed in Swift 3.

loadNibNamed(_:owner:topLevelObjects:) has been introduced in macOS 10.8 and was present in all versions of Swift. However loadNibNamed(nibName:owner:options:) has been dropped in Swift 3.

The signature of the method is

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

so you have to create an pointer to get the array of the views on return.

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
}

Edit: I updated the answer to filter the NSView instance reliably.


In Swift 4 the syntax slightly changed and using first(where is more efficient:

var topLevelObjects : NSArray?
if Bundle.main.loadNibNamed(assistantNib, owner: self, topLevelObjects: &topLevelObjects) {
     return topLevelObjects!.first(where: { $0 is NSView }) as? NSView
}
like image 148
vadian Avatar answered Sep 30 '22 10:09

vadian


Swift 4 version of @vadian's answer

var topLevelObjects: NSArray?
if Bundle.main.loadNibNamed(NSNib.Name(rawValue: nibName), owner: self, topLevelObjects: &topLevelObjects) {
    return topLevelObjects?.first(where: { $0 is NSView } ) as? NSView
}
like image 32
Ryan H Avatar answered Sep 30 '22 10:09

Ryan H