Connecting a SpriteKit application with the TouchBar
By: Henrique Conte
Tags: Macos, Spritekit, Touch Bar, Swift, Programming

First of all, we have to pay attention to the type of project we are creating: a touch bar only exists on MacBooks, therefore we should create a macOS project in order to facilitate our work.

Having it created, we are able to start coding. If your MacBook doesn’t have a physical touch bar, you can use the Xcode simulator clicking on Window > Touch Bar > Show Touch Bar.

How can I support the Touch Bar?

When we want to use elements provided by the system and its functions, like Table Views and Text Fields, we adopt their delegate protocols. Well, for the touch bar it wouldn’t be different, right? In this application, we are going to implement two protocols: NSTouchBarProvider and NSTouchBarDelegate.

In this project specifically, we are doing it at our AppDelegate, but this is not a rule. Go to AppDelegate.swift and add the following at the end of the file:

extension AppDelegate: NSTouchBarDelegate, NSTouchBarProvider { var touchBar: NSTouchBar? { let bar = NSTouchBar()

bar.delegate = self

bar.defaultItemIdentifiers = [.touchBarView]



return bar

}

}

Here you will be declaring touchBar, which is required for the protocol NSTouchBarProvider, responsible for your view to instantiate a touch bar. Notice that here you also:

Created a touchBar. Set the delegate. Set the default item identifiers, that tells what will be displayed on the touch bar.

Nevertheless, we still didn’t create a proper default item identifier. In the same file, add this to the code:

extension NSTouchBarItem.Identifier { static let touchBarView = NSTouchBarItem.Identifier(“com.spriteKit.touchBar”) }

The string used to declare the identifier can be anything, just remind not to create two identifiers with the same string.

If you compile and run now, you will see that the touch bar is still empty, and that’s because we haven’t instantiated anything in there, and that is what we are going to do now.

Create a variable called touchBarView of the type TouchBarView inside your AppDelegate.

Inside the NSTouchBarDelegate and NSTouchBarProvider extension, below the NSTouchBar variable, write the following:

func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? { switch identifier {

case NSTouchBarItem.Identifier.touchBarView: let item = NSCustomTouchBarItem(identifier: .touchBarView) if touchBarView == nil {

touchBarView = TouchBarView()

} item.viewController = touchBarView return item

default: return nil

}

}

Here we will be creating touch bar items according to their identifiers, and we use a switch to act differently with each one of them. To do that, we instantiate a NSCustomTouchBarItem and add the elements we want it to show. Since our goal is to use a SpriteKit scene, we will want it first to present a View Controller.

Adding a View Controller to the Touch Bar

While adding the previous code, you noticed that we don’t have the “TouchBarView” class, so let’s add it! Create a new Swift File and add the following:

import Cocoa

import Foundation

import SpriteKit class TouchBarView: NSViewController { override func viewDidLoad() {

super.viewDidLoad()

} override func loadView() {



} override func viewDidAppear() {

super.viewDidAppear()

}

}

This is a basic view controller with its basic methods, and that is what is being presented by the touch bar now. If we want to have a SpriteKit scene on it, we should first create a SKView variable with the size of the touch bar, so add this inside the class:

private lazy var gameView: SKView = { let view = SKView(frame: self.view.bounds)

view.autoresizingMask = [.width, .height] return view

}()

Now we have a SKView, let’s use it! Add the following code inside loadView() method to add the SKView to our existent view:

view = NSView()

view.addSubview(gameView)

If you run the project now, you will see we have good news! Now the touch bar seems to be white, and that happens because it is showing now our SKView :)

Let’s now present a SKScene there, therefore we will be able to add whatever we want to our touch bar. In order to do that, add the following to our viewDidAppear():

override func viewDidAppear() {

super.viewDidAppear() if gameView.scene == nil { let scene = SKScene(fileNamed: "StartScene") as? StartScene

scene!.scaleMode = .aspectFill gameView.presentScene(scene)

}

}

We still don’t have the class StartScene, and that’s what we are going to do now.

Connecting to the SKScene

We are almost there! Now, we have to create the SKScene that we are going to present.

Go to you scene file (.sks) and adjust the width to 690 and the height to 30.

And one more thing with the scene file! Write StartScene in the Custom Class field. Doing that, we will have defined the size of the scene and the class that it will display.

Finally, we got to the final step! Now we should create the class we defined as custom on our .sks file, so let’s do it. Create a new Swift File and add the following code:

import Foundation

import SpriteKit class StartScene: SKScene { override func didMove(to view: SKView) { let backgroundNode = SKSpriteNode(color: NSColor(red: 95/255, green: 75/255, blue: 139/255, alpha: 1.0), size: view.bounds.size) let labelNode = SKLabelNode(text: “Congratulations! ;]”)

labelNode.position = CGPoint(x: 0, y: -5)

labelNode.fontSize = 16

labelNode.fontColor = NSColor(red: 230/255, green: 154/255, blue: 141/255, alpha: 1.0) addChild(backgroundNode)

addChild(labelNode)

}

}

This will instantiate our SKScene and add two nodes to demonstrate that we can use it in our touch bar just like we use on other devices. If you compile and run the project, it should now look like this.

Our initial objective was to connect the touch bar with a SpriteKit application, so we won’t go any further on the implementation. However, if you want to adventure yourself, here is a simple example of what is possible to do, available to download here: