Я не Swift разработчик, и даже не objc. У меня просто был и есть Mac с навороченной вставкой в виде Touch Bar для которой захотелось сделать кастомизацию.

Эта статья покажет всем не iOS разработчикам как можно НАЧАТЬ создавать простые приложухи (развлекательного или полезного характера) для Touch Bar с самых первых этапов.

Притупим к делу :

  1. Открываем xCode > Create a new project -> App

    Пример заполнения формы. Важно выбрать Storyboard, так как работать мы будем именно с ней.
    Пример заполнения формы. Важно выбрать Storyboard, так как работать мы будем именно с ней.

    Существует несколько путей создания своего приложения для ios, один из них визуальное программирования с использованием Storyboard, это когда вы не пишете условно говоря :

    view.attend(newElement(slider))

    А просто добавляете этот самый newElement(slider) на ваш Storyboard и потом программируете viewController используя объект.

    Заканчиваем создание проекта и видим такую структуру:

    Такая структура
    Такая структура
  2. Переходим в Main.storyboard и видим развертку нашего приложения и что с чем коммуницирует, наблюдаем и точку входа. Но нам это сейчас неважно, кликаем на Windows окошко.

    Окошко
    Окошко
  3. Добавляем новый элемент в правом верхнем углу xCode есть жирний плюсик, вот туда тыкаем и ищем "NsTouchBar" и добавляем этот перетягиванием на Window. Теперь у нашего приложения есть свой Touch Bar.

    Если мы прямо сейчас запустим приложение, пройдёт время компиляции и мы увидим пустой Touch Bar.

    Тут важно что элементы справа, так же называемые Control Strip, будут присутствовать так как это часть private api macOs, что бы её менять нужно применять reverse engineering, на этом туториале такой задачи не стоит.

  4. Что бы добавить элементы на наш тачбар пишем "NsTouchBar Button" и Enter, нам нужно две кнопки. На одну мы повесим вывод изображения, другая будет триггером.
    Поэтому следующим этапом берем обычный ImageView и перетаскиваем прямо на одну из кнопок.

    На этом шаге такой результат должен получится:

    Our storyboard, yolo!
    Our storyboard, yolo!
  5. Далее нужно создать класс WindowController и добавить его к обработчику Storyboard.
    Нажимаем в строке меню, File -> New -> File -> Cocoa Class

    Создание обработчика. Важно указать в качестве Subclass : NsWindowController!
    Создание обработчика. Важно указать в качестве Subclass : NsWindowController!

    Что такое Cocoa, грубо говоря либа для разработки, которая по моим скромным исследованиям не очень просто дружит с SwiftUI, ещё одним мощным инструментом разработки, который в свою очередь противоположен Storyboard.

  6. Далее нужно подключить наш обработчик, к обработчику Storyboard:

    1. Открываем Storyboard

    2. Выбираем Window Controller Scene в меню сцен Storyboard > Window Controller

    3. Открываем Inspectors > Identity Inspector

    4. Выбираем наш WindowController в качестве Custom class.

  7. Добавляем элементы Touchbar на WindowController

    1. Используя Add Editor on <<side>>, открываем два редактора, в одном обработчик, в другом Storyboard.

    2. С зажатой клавишей Control, перетаскиваем Button как показано на рисунке. И добавляем имя переменной (какое хотите).

      Вот такая паутина спайдермена пуляете её прямо в код!
      Вот такая паутина спайдермена пуляете её прямо в код!
    3. Так же делаем с View, важно перетаскивает не Touch Bar View айтем, а то что находится вложенным в View Controller.

На этом этап подготовительных работ закончен, и начинается реализация чего угодно.
Давайте для примера сделаем кнопку, которая показывает гифку котика, после чего меняется своё название и по второму нажатию прячет котика.

Отобразим через Window -> Touch Bar -> Touch bar (2nd generation) сам тачбар, что бы я мог показать результат, например ><&

Вся работа будет с файлом `WindowController.swift`, кто ещё помнит, этот тот контроллер, который мы подключили к Storyboard.

Названия и вид переменных:

    @IBOutlet weak var switcher: NSButton!
    @IBOutlet weak var image_view: NSImageView!

Допишем вызов функции установки изображения:

   override func windowDidLoad() {
            super.windowDidLoad()
            switcher.action = #selector(self.set_image)
        }

и допишем саму функцию:

        @objc func set_image(){
          //Ссылаемся на наш Bundle
            let app_bundle = Bundle.main
					//Если анимации нету, то нету и изображения
            if (!image_view.animates) {
					//Берём путь относительно нашего Bundle, файл называется nyan.gif
            let path = app_bundle.path(forResource: "nyan", ofType: "gif")!
              // Добавляем файл в качестве изображения к кнопке с image view
                image_view.image = NSImage.init(byReferencingFile: path)
							// Говорим что она движется
                image_view.animates = true
              // Меняем названия кнопки-триггера, что бы она показывала действия спрятать изображение 
                switcher.title = "de-nyanifaction"
            } else {
              // Точно так же если изображение спрятано меняем title кнопки
                switcher.title = "nyanifaction"
              // Тот самый момент, что, если нету анимации то нету изображения
                image_view.animates = false
              // Убираем изображение
                image_view.image = nil;
            }
        }

Весь файл (обработчика) целиком:

//
//  WindowController.swift
//  nyan_warrior
//
//  Created by nanallew on 05.05.2021.
//

import Cocoa

class WindowController: NSWindowController {

    @IBOutlet weak var switcher: NSButton!
    @IBOutlet weak var image_view: NSImageView!
    
        @objc func set_image(){
            let app_bundle = Bundle.main
            if (!image_view.animates) {
            let path = app_bundle.path(forResource: "nyan", ofType: "gif")!
                image_view.image = NSImage.init(byReferencingFile: path)
                image_view.animates = true

                switcher.title = "de-nyanifaction"
            } else {
                switcher.title = "nyanifaction"
                image_view.animates = false
                image_view.image = nil;
            }
        }

        override func windowDidLoad() {
            super.windowDidLoad()
            switcher.action = #selector(self.set_image)
        }
    
}

Запускаем приложения и смотрим на бар:

Какая полезная фича
Какая полезная фича

На этом всё друзья, спасибо за внимание.

Github rep. as a source.