Do you need help on a specific subject? Use the contact form (Request a blog entry) on the right hand side.

2015-12-03

Swift example: How to load a nib/xib file into a view on OS-X

Many simple application use just a single nib/xib file, the MainMenu.xib. And while that works fine, as soon as the application becomes more demanding it gets cramped rather quickly.
Also, Apple suggests that the MainMenu.xib file should only be used for the main menu and that we should add xib files for other windows and views as necessary.

This post shows how to load a view from a different xib file and make it visible. We wil do this the old fashioned way, without storyboards.

For non-document based applications I will use MainMenu.xib for the menu and the main window. Then I will add another xib file containing a view. This view will be loaded into the main window explicitly. The view will use a NSViewController.

Create the project, a simple cocoa application for OS-X. This project comes with the main menu xib already set up the way this example needs it.

Since we want to load a view from a different nib into the window, it would be nice to have access to the view component of the window. To do this, add an outlet to the AppDelegate. Also, we will need an instance of NSViewController to attach the loaded view to, create it in AppDelegate as well:

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!

    @IBOutlet weak var view: NSView!
    
    var myViewController = MyViewController!

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
    }

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }

}

In Interface builder, connect the view outlet to the view inside the window. Select the "Window". Right-click the delegate object, click drag the circle behind the "view" and drag it onto the window. When completed it should look like this:



Now create a new OS-X User Interface file. Select the "View" template. I saved it as MyView.xib. In this view I added a textfield and a button like this:



Next, create the view controller. Add a new Swift file called MyViewController.swift to the project. In it, add an outlet for the textfield and an action for the button:

import Foundation
import Cocoa

class MyViewController: NSViewController {
    
    @IBOutlet weak var textField: NSTextField!
    
    @IBAction func countButtonAction(sender: AnyObject?) {
        var count = textField.integerValue
        count++
        textField.integerValue = count
    }

}

Switch back to the MyView.xib file and change the class of the File Owner to MyViewController:


Connect the outlet and action to the textfield and the button. And important: Also connect the "view" outlet to our new view:



Almost done, now the final step: loading the nib file and displaying its contents. We do this in the AppDelegate:

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!

    @IBOutlet weak var view: NSView!
    
    var myViewController: MyViewController!

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
        myViewController = MyViewController(nibName: nil, bundle: nil)
        view.subviews.removeAll()
        view.addSubview(myViewController.view)
    }

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }

}

That is all, build and run the project.

You will notice that you need to clean up the appearance of the window, but for today, I will leave that exercise for you.

Note: The name of the nib file (or xib file) must be the same as the name for the ViewController. Otherwise the instantiation of the controller will fail.

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

No comments:

Post a Comment