Duck
Duck

Reputation: 35993

NSArray contains two elements but myArray[0] is nil?

I am trying to load a NIB from file.

I have this code, from here

protocol NibLoadable {
  static var nibName: String? { get }
  static func createFromNib(in bundle: Bundle) -> Self?
}

extension NibLoadable where Self: NSView {

  static var nibName: String? {
    return String(describing: Self.self)
  }

  static func createFromNib(in bundle: Bundle = Bundle.main) -> Self? {
    guard let nibName = nibName else { return nil }
    var topLevelArray: NSArray? = nil
    bundle.loadNibNamed(NSNib.Name(nibName), owner: self, topLevelObjects: &topLevelArray)
    guard let results = topLevelArray else { return nil }
//    let views = Array<Any>(results).filter { $0 is Self }
//    return views.last as? Self
    let element =      results[0] as? Self

    return results[0] as? Self
  }
}

results have two elements, a NSView and NSApplication.

The problem here is the element is nil. The commented code was also giving me nil there.

I am new to swift. What is this Self delivering or what it represents on the last line of createFromNib?

Upvotes: 0

Views: 68

Answers (2)

Duck
Duck

Reputation: 35993

After hours trying to fiddle with non-existent documentation, I have come with this, much simpler.

  func loadViewFromNib() {

    var topLevelArray : NSArray?

    let bundle = Bundle(for: type(of: self))
    let nib = NSNib(nibNamed: .init(String(describing: type(of: self))), bundle: bundle)!
    nib.instantiate(withOwner: self, topLevelObjects: &topLevelArray)

    let myView = topLevelArray?.first(where: { $0 is NSView }) as? NSView
    addSubview(myView!)
}

Thanks @vadian for all the effort.

Upvotes: 0

vadian
vadian

Reputation: 285150

It's not guaranteed that the first object is the requested view.

Get the proper view with first(where

And declare nibName non-optional as a requirement.

protocol NibLoadable {
    static var nibName: String { get }
    static func createFromNib(in bundle: Bundle) -> Self?
}

extension NibLoadable where Self: NSView {    
    static var nibName: String {
        return String(describing: Self.self)
    }

    static func createFromNib(in bundle: Bundle = Bundle.main) -> Self? {
        var topLevelArray: NSArray? // Optionals are nil by default
        bundle.loadNibNamed(NSNib.Name(nibName), owner: self, topLevelObjects: &topLevelArray)
        return topLevelArray?.first(where: { $0 is Self }) as? Self
    }
}

Upvotes: 1

Related Questions