Swift 3 Download xib. NSBundle.mainBundle (). LoadNibNamed return Bool

I tried to figure out how to create a custom view using xib files. This question uses the following method.

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 the previous code generates . The Bool type has no index members , which is obvious since the return type is Bool.

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

+6
source share
3 answers

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

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

Method signature

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

so you need to create a pointer to get an array of returned views.

 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 reliably filter the instance of NSView .


In Swift 4, the syntax has changed a bit and using first(where more efficient:

 var topLevelObjects : NSArray? if Bundle.main.loadNibNamed(assistantNib, owner: self, topLevelObjects: &toplevelObjects) { return topLevelObjects!.first(where: { $0 is NSView }) as? NSView } 
+8
source

Swift 4 answer version @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 } 
+2
source

I wrote an extension that is safe and easy to download from 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 } } 

Then just use it like this:

 let view: CustomView = .fromNib() 

Is CustomView subclass of NSView as well as CustomView.xib .

0
source

Source: https://habr.com/ru/post/1012272/


All Articles