Slide 1

Slide 1 text

How to Make a Touch Bar App

Slide 2

Slide 2 text

Outline • What is a Touch Bar ! • Read the Docs " • Write the Code #

Slide 3

Slide 3 text

What is a Touch Bar !

Slide 4

Slide 4 text

About the Touch Bar1 • Retina display • Input device • Dynamic interface • Touch ID 1 https:/ /developer.apple.com/library/content/documentation/UserExperience/Conceptual/OSXHIGuidelines/AbouttheTouchBar.html

Slide 5

Slide 5 text

Gestures2 • Tap • Touch and hold • Horizontal swipe (pan) • Multitouch 2 https:/ /developer.apple.com/library/content/documentation/UserExperience/Conceptual/OSXHIGuidelines/Interaction.html

Slide 6

Slide 6 text

Read the Docs !

Slide 7

Slide 7 text

Open this NSTouchBar API Reference

Slide 8

Slide 8 text

At a Glance • SDK: macOS 10.12.1+ • NSTouchBar: a bar • NSTouchBarItem: an item

Slide 9

Slide 9 text

Musts 1. Be a responder (an instance of an NSResponder subclass) that is present within a responder chain at runtime 2. Conform to the NSTouchBarProvider protocol 3. Implement the makeTouchBar() method within that protocol

Slide 10

Slide 10 text

At a Glance (cont.) • NSTouchBar: customizationIdentifier • NSTouchBarItem: • defaultItemIdentifiers • customizationAllowedItemIdentifiers • customizationRequiredItemIdentifiers • NSTouchBarDelegate: delegate

Slide 11

Slide 11 text

Write the Code !

Slide 12

Slide 12 text

Environment3 • macOS Sierra 10.12.1 (16B2657) • Xcode 8.1 (8B62) 3 https:/ /developer.apple.com/macos/touch-bar/

Slide 13

Slide 13 text

Sample Project is here

Slide 14

Slide 14 text

Show Touch Bar Simulator4 • Show the Touch Bar simulator by choosing Window > Show Touch Bar (⇧⌘5) 4 https:/ /help.apple.com/xcode/mac/8.1/#/dev7a8cb8a8c

Slide 15

Slide 15 text

Preview

Slide 16

Slide 16 text

Project Init • Create a new Xcode project • Template > macOS > Cocoa Application > Next • Product name, organization name, etc.

Slide 17

Slide 17 text

Project Init (cont.)

Slide 18

Slide 18 text

Folder Tree • AppDelegate.swift • ViewController.swift • Main.storyboard • Assets.xcassets • Info.plist

Slide 19

Slide 19 text

Main.storyboard • Delete Window Controller Scene • Delete View Controller Scene

Slide 20

Slide 20 text

Add our WindowController • File > New > File... (⌘N) • Cocoa Class > Next • Subclass of: NSWindowController • ✅ Also create XIB file for user interface

Slide 21

Slide 21 text

Add our WindowController (cont.)

Slide 22

Slide 22 text

Window Controller • Single-window / Multi-window • Entrance: • AppDelegate.swift • application(_:didFinishLaunchingWithOptions:)

Slide 23

Slide 23 text

AppDelegate - iOS import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { window = UIWindow(frame: UIScreen.mainScreen().bounds) let storyboard = UIStoryboard(name: "Main", bundle: nil) let rootVC = storyboard.instantiateViewControllerWithIdentifier("RootVC") window?.rootViewController = rootVC window?.makeKeyAndVisible() return true } }

Slide 24

Slide 24 text

AppDelegate - macOS import Cocoa @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { var windowController: NSWindowController? func applicationDidFinishLaunching(_ aNotification: Notification) { let windowController = WindowController(windowNibName: "WindowController") windowController.showWindow(self) self.windowController = windowController } }

Slide 25

Slide 25 text

Differences • import UIKit → import Cocoa • UI- prefix → NS- prefix • Simple enough! !

Slide 26

Slide 26 text

WindowController.xib • 5 NSTextFields • 1 NSButton

Slide 27

Slide 27 text

WindowController.xib (cont.)

Slide 28

Slide 28 text

Musts Again 1. Be a responder (an instance of an NSResponder subclass) that is present within a responder chain at runtime 2. Conform to the NSTouchBarProvider protocol 3. Implement the makeTouchBar() method within that protocol

Slide 29

Slide 29 text

Step 1: Become a Responder • We've created a WindowController open class NSWindowController : NSResponder, NSCoding, NSSeguePerforming { public init(window: NSWindow?) } • Yes, it's an instance of an NSResponder subclass!

Slide 30

Slide 30 text

Step 2: Conform to the Protocol public protocol NSTouchBarProvider : NSObjectProtocol { @available(OSX 10.12.1, *) public var touchBar: NSTouchBar? { get } } extension NSResponder : NSTouchBarProvider { @available(OSX 10.12.1, *) open var touchBar: NSTouchBar? @available(OSX 10.12.1, *) open func makeTouchBar() -> NSTouchBar? } • Yes, it conforms to the NSTouchBarProvider protocol!

Slide 31

Slide 31 text

Step 3: Implement the Method • Haven't yet! !

Slide 32

Slide 32 text

Make Touch Bar Great Again • Open WindowController.swift • Code!

Slide 33

Slide 33 text

Identifiers fileprivate extension NSTouchBarCustomizationIdentifier { static let touchBar = NSTouchBarCustomizationIdentifier("io.Cee.TouchBarSample.touchBar") } fileprivate extension NSTouchBarItemIdentifier { static let smaller = NSTouchBarItemIdentifier("io.Cee.TouchBarSample.smaller") static let equal = NSTouchBarItemIdentifier("io.Cee.TouchBarSample.equal") static let bigger = NSTouchBarItemIdentifier("io.Cee.TouchBarSample.bigger") }

Slide 34

Slide 34 text

Create a Bar // MARK: - NSTouchBar @available(OSX 10.12.1, *) override func makeTouchBar() -> NSTouchBar? { let touchBar = NSTouchBar() touchBar.delegate = self touchBar.customizationIdentifier = .touchBar touchBar.defaultItemIdentifiers = [.smaller, .equal, .bigger] touchBar.customizationAllowedItemIdentifiers = [.smaller, .equal, .bigger] return touchBar }

Slide 35

Slide 35 text

Create Bar Items extension WindowController: NSTouchBarDelegate { @available(OSX 10.12.1, *) func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItemIdentifier) -> NSTouchBarItem? { let touchBarItem = NSCustomTouchBarItem(identifier: identifier) var title: String switch identifier { case NSTouchBarItemIdentifier.smaller: title = "<" case NSTouchBarItemIdentifier.equal: title = "=" case NSTouchBarItemIdentifier.bigger: title = ">" default: title = "" } let touchBarButton = NSButton(title: title, target: self, action: #selector(compare(with:))) touchBarItem.view = touchBarButton return touchBarItem; } }

Slide 36

Slide 36 text

Components @IBOutlet weak var numberA: NSTextField! @IBOutlet weak var numberB: NSTextField! @IBOutlet weak var resultLabel: NSTextField!

Slide 37

Slide 37 text

Compare func compare(with symbol: NSButton) { let number1 = numberA.intValue let number2 = numberB.intValue var result: Bool switch symbol.title { case "<": result = (number1 < number2) case "=": result = (number1 == number2) case ">": result = (number1 > number2) default: result = false } resultLabel.stringValue = (result == true) ? "Correct" : "Wrong" }

Slide 38

Slide 38 text

Randomize // MARK: - Button Action @IBAction func randomize(_ sender: NSButton) { reset() } // MARK: - Private Method func reset() { numberA.intValue = randomAInt() numberB.intValue = randomAInt() resultLabel.stringValue = "" } func randomAInt() -> Int32 { return Int32(arc4random_uniform(10)) }

Slide 39

Slide 39 text

Initialization override func windowDidLoad() { super.windowDidLoad() reset() }

Slide 40

Slide 40 text

Where to Go From Here • How to write a macOS app • Cocoa programming

Slide 41

Slide 41 text

About Me • ሴॠਜ a.k.a. Cee • Serve at: Raven Lab • Mail: [email protected] • GitHub: Cee • Twitter: Ceecirno • Weibo: ྺ෫ਂࣁఽጱCee

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

Thank You For Listening