2

I have a viewcontroller with a custom view area on the top, as seen in the below image enter image description here

I want to load a custom xib into this area and I am struggling to do so. I created a ABC.swift file which is a subclass of NSView and a .xib file with the same name. In the .xib file from the identity inspector I set the class ABC. Then in my viewcontroller's viewDidLoad() I try to do the following

let abcView = Bundle.main.loadNibNamed("ABC", owner: self, topLevelObjects: nil) as ABC

I also created an outlet for the custom view in my vc then in viewDidLoad()

customView.addSubview(abcView)

But this not working as abcView is of type Bool. Can anyone tell me what am I doing wrong? What is the best way to achieve my goal?

2
  • Duplicate: stackoverflow.com/questions/27228362/… Commented Aug 8, 2017 at 11:58
  • @ElTomato i dont know how to convert it to swift 3 syntax. also i m a bit confused between the connections once has to make with the storyboard. let abcView = Bundle.main.loadNibNamed("ABC", owner: self, topLevelObjects: nil) returns bool. How can i add this to subview ? Commented Aug 8, 2017 at 14:44

3 Answers 3

3

I use the following Extension on NSView : (same as answer given by user Accepted Answer)

import Foundation
import Cocoa

extension NSView {

    static func loadFromNib(nibName: String, owner: Any?) -> NSView? {

        var arrayWithObjects: NSArray?

        let nibLoaded = Bundle.main.loadNibNamed(NSNib.Name(rawValue: nibName), owner: owner, topLevelObjects: &arrayWithObjects)

        if nibLoaded {
            guard let unwrappedObjectArray = arrayWithObjects else { return nil }
            for object in unwrappedObjectArray {
                if object is NSView {
                    return object as? NSView
                }
            }
            return nil
        } else {
            return nil
        }
    }
}

This is how to use it in loadView() of an NSViewController :

if let loadedNavButtons: NavigationButtonsView = NSView.loadFromNib(nibName: "NavigationButtonsView", owner: self) as? NavigationButtonsView {
    // Do whatever you want with loadedNavButtons
}

Works in Swift 4 , XCode 9.2

Sign up to request clarification or add additional context in comments.

1 Comment

Where arrayWithObjects is initialized?
0

As of this writing, macOS only has a legacy means of bundle loading: func loadNibNamed(_ nibName: NSNib.Name, owner: Any?, topLevelObjects: AutoreleasingUnsafeMutablePointer<NSArray?>?) -> Bool.

It shall pass the top-level objects of the nib in the array you supplied as the last argument:

var objs = NSArray()
Bundle.main.loadNibNamed("MyScreen", owner: self, topLevelObjects: &objs)

Be sure to check it returned true. Otherwise it means it could not load the desired nib.

After it's loaded, the objects in the left-hand menu in the Interface Builder are available in your code. If you have a View in your nib, you can add it as a subview:

for obj in objs {
  if obj is MyViewClass {
    // Now we are sure that the obj is really a view of the desired class
    self.someView.addSubview(obj)
  }
}

2 Comments

so is there a better way to do what i want to do ?
@sumesh, well, you can use the same storyboard for everything and try something like this: developer.apple.com/documentation/appkit/nsstoryboard/…
0

A slightly more compact version of answer already given

extension NSView {

    static func loadFromNib(nibName: String, owner: Any? = nil) -> NSView? {
        var arrayWithObjects: NSArray?
        let nibLoaded = Bundle.main.loadNibNamed(NSNib.Name(rawValue: nibName),
                                                 owner: owner,
                                                 topLevelObjects: &arrayWithObjects)

        if nibLoaded {
            return arrayWithObjects?.first(where: { $0 is NSView }) as? NSView
        }

        return nil
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.