Connecting a SpriteKit application with the TouchBar

Henrique Conte
Swift Developer Academy Porto Alegre
6 min readApr 27, 2020

Have you started using your touch bar and thought “why the hell do I need this in my computer”? Well, now we found some use for it! The touch bar was released in 2016, and since then users and developers have been trying to innovate on its use. Today, we will go through a simple and fast way to allow SpriteKit applications to be used on our dear touch bar.

Note: For this tutorial, you will need Xcode version 8.1 or later and macOS 10.12.2 or later.

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:

  1. Created a touchBar.
  2. Set the delegate.
  3. 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.

  1. 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 = touchBarViewreturn 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:

If you want to check the game code, click here:

Where to go from here?

In this tutorial, you learned the following:

  1. How to setup your app to support theTouch Bar.
  2. How to connect the Touch Bar with a custom View Controller.
  3. How to connect your custom View Controller to a SKScene.

If you want to go further on the app, you can implement features on your SKScene to understand better how the touch bar screen works and its limitations. Besides, I challenge you to make an interactive app using the touch bar and a Mac application.

References

For similar tutorials and projects, I would recommend the following sites:

--

--

Henrique Conte
Swift Developer Academy Porto Alegre

iOS Developer at Apple Developer Academy | PUCRS and Computer Science student at UFRGS