-
-
Notifications
You must be signed in to change notification settings - Fork 164
How to use nib files with DarwinKit
Assumptions made in this tutorial
- Have Xcode installed
- Have DarwinKit installed
- Running Mac OS
System Requirements
- Xcode version: unknown
- Mac OS version: unknown
- Go version: 1.18 or higher
- DarwinKit: commit 6a98f82290e53bc5d82cb59436644f705156d7cb or
higher
Do you like to program in Go?
Do you want to make programs for Mac OS?
Do you want your applications to be disk space and RAM efficient?
Do you want to use the AppKit framework to make your application's
GUI?
Do you want to create an user interface with drag and drop ease?
If you said yes to these questions then you are in the right
place.
With DarwinKit you
can create full Mac OS applications. There is no need to use code
to create the user interface. You can use nib files and Xcode to
create them. This tutorial will take you step by step thru the
application creation process.
Directions:
- Start Xcode.
- Create a new empty XIB file by going to File -> New ->
macOS-> User Interface -> Empty.
- Push the Next button and save the file as MainMenu.xib.
- Show the library by going to View->Show Library.
- In the search field at the top enter "window".
- Drag this window object to the middle of the window while
holding down the Option key.
Note: Holding down the Option key initially makes the Library window stay open for subsequent drags.
- Next search for a push button.
- Drag this control to the window.
- Then find a textfield and drag it onto the window.
- You may close the Library window now if you wish.
- Click on the textfield to select it.
- Click on this button to show the Attributes Inspector.
- In the Attributes window scroll down to the View section.
- In the Tag field enter 1.
- Do the same thing for the push button except enter 2 this time.
-
Click
on the window's title bar.
-
In the Attributes window under the Window selection enter "My Go Application" in the Title section. This will set the window's title to "My Go Application".
-
Click on the button.
- In the Attributes window in the Title field set the button's
title to "Push".
- Create a new empty file called main.go.
- Save this file in the same folder as the xib file.
- Copy and paste this code into the file:
// File: main.go // Description: Uses a NIB file to display the interface // Run directions: go run main.go package main import ( "fmt" "os" "github.com/progrium/macdriver/macos/appkit" f "github.com/progrium/macdriver/macos/foundation" "github.com/progrium/macdriver/objc" "github.com/progrium/macdriver/helper/action" "unsafe" ) // used by both main() and doButton() var textField appkit.TextField func main() { // setup the application app := appkit.Application_SharedApplication() app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular) app.ActivateIgnoringOtherApps(true) // get the nib file's data godata, err := os.ReadFile("MainMenu.nib") handleError(err != nil, "Failed to load nib file") myNib := appkit.NewNibWithNibDataBundle(godata, nil) // obtain all root level objects from the nib file var myObjects = f.Array_Array() status := myNib.InstantiateWithOwnerTopLevelObjects(nil, unsafe.Pointer(&myObjects)) handleError(status == false, "Failed to instantiate nib file") // find the window and display it // assumes there is only one window object at the root level var i uint var mainWindow appkit.Window for i = 0; i < myObjects.Count(); i++ { theObject := myObjects.ObjectAtIndex(i) if theObject.IsKindOfClass(objc.GetClass("NSWindow")) { mainWindow = appkit.WindowFrom(theObject.Ptr()) mainWindow.OrderFront(nil) break } } // if the window was not found handleError(mainWindow.IsNil(), "Failed to find the window object") // setup the button aButton := mainWindow.ContentView().ViewWithTag(1) handleError(aButton.IsNil(), "Failed to find the button object") action.Set(appkit.ButtonFrom(aButton.Ptr()), doButton) // setup the textfield textFieldView := mainWindow.ContentView().ViewWithTag(2) handleError(textFieldView.IsNil(), "Failed to find the textfield object") textField = appkit.TextFieldFrom(textFieldView.Ptr()) // start the main loop app.Run() } // handles any error situations func handleError(isProblem bool, errorMessage string) { if isProblem == true { panic(errorMessage) } } // called when the user pushes the button func doButton(sender objc.Object) { fmt.Println("button pushed") textField.SetStringValue("You pushed the button") }
- Open the Terminal application.
- cd to the folder that contains all the project files.
- Run this command to setup the program:
go mod init program
- Then open the file go.mod and add these lines to the end of
the file:
require github.com/progrium/macdriver v0.5.0
replace github.com/progrium/macdriver => <path to your darwinkit folder>
- Fill in the path of your local repo in the last line. Be sure there is at least one space between the '=>' and the start of your path.
- Convert the MainMenu.xib file to a nib file using this
command:
ibtool --compile MainMenu.nib MainMenu.xib
- Now you will run this program using this command:
go run main.go

Issues
If you see this error while using the ibtool:
xcode-select: error: tool 'ibtool' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
Run this command to fix this problem:
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
How the Program Works
The root level of the nib file contains four items, File's Owner,
First Responder, Application, and the window we created. The Nib
method InstantiateWithOwnerTopLevelObjects() is used to get all
the root level objects and place them into an array. The loop in
the main() function is used to look thru each object in the array.
If it finds an object that is of type NSWindow then we have found
the window we created.
The button and the textfield are looked up by tag number, bound
to local variables, and then setup for use.