Touch Bar

For my A level Computer Science project I have created an app for iOS/iPadOS which allows users to take or select a picture and extract the text from that image.

Using a Mac Catalyst, my app also works well on Mac, however I would like to add some customisation features so that it looks and feels better on a Mac.

I have created a Touch Bar storyboard and was wondering if I could add it to my app, I was thinking of something along the lines of 'If User device = Mac then load TouchBarStoryboard else don't'.

If you have any ideas on how I could implement this, please do let me know.

Below is an image of the storyboard I created for the Touch Bar.

On iOS, my GUI looks like this:

Therefore I thought the Touch Bar would offer the user an alternative to using the mouse when switching between the 5 tabs.

Many thanks for your help.

I have written some code in a separate file which is shown below. I don't know whether this code works or not because when I run my app on Mac, nothing appears on my Touch Bar. I am sure I need to call the class somewhere within my app but I don't know where.

Any thought on this would be much appreciated. Many thanks.

#if targetEnvironment(macCatalyst)
import Cocoa
class TouchBarViewController: NSViewController {
    let button = NSTouchBarItem.Identifier("com.TouchBarCatalog.TouchBarItem.button")
    let buttonBar = NSTouchBar.CustomizationIdentifier("com.TouchBarCatalog.buttonBar")
    @IBOutlet weak var HelpButton: NSButton!
    @IBOutlet weak var PhotosButton: NSButton!
    @IBOutlet weak var CameraButton: NSButton!
    @IBOutlet weak var HistoryButton: NSButton!
    @IBOutlet weak var SettingsButton: NSButton!
}
// MARK: - Action Functions
override func viewDidLoad() {
    super.viewDidLoad()
}
override func makeTouchBar() -> NSTouchBar? {
    let touchBar = NSTouchBar()
    touchBar.delegate = self
    touchBar.customizationIdentifier = buttonBar
    touchBar.defaultItemIdentifiers = [button]
    return touchBar
}
@IBAction func customize(_ sender: AnyObject) {
    guard let touchBar = touchBar else { return }
    for itemIdentifier in touchBar.itemIdentifiers {
        guard let item = touchBar.item(forIdentifier: itemIdentifier) as? NSButtonTouchBarItem,
            let button = item.view as? NSButton else { continue }
        button.bezelColor = useCustomColor.state == NSControl.StateValue.on ? NSColor.systemYellow : nil
    }
}
@IBAction func buttonAction(_ sender: AnyObject) {
    if let button = sender as? NSButtonTouchBarItem {
        print("\(#function): button with title \"\(button.title)\" is tapped")
    }
}
}
// MARK: - NSTouchBarDelegate
extension TouchBarViewController: NSTouchBarDelegate {
// The system calls this while constructing the NSTouchBar for each NSTouchBarItem you want to create.
func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
    switch identifier {
    case button:
        let buttonItem = NSButtonTouchBarItem(identifier: identifier)
        buttonItem.title = NSLocalizedString("Button", comment: "")
        buttonItem.target = self
        buttonItem.action = #selector(buttonAction)
        buttonItem.image = NSImage(systemSymbolName: "tray", accessibilityDescription: "tray")
        return buttonItem
    default:
        return nil
    }
}
}

#endif

The code for my GUI is shown below. I am thinking perhaps the class TouchBarViewController needs to be called here?

Something else I require is that when the user clicks on one of the 5 items in the Touch Bar, it will change the tabSelection in my GUI accordingly. For example, if the user taps on the first item in the Touch Bar, they should be taken to HelpView()/ContentView5. Or if the user taps on the second item in the Touch Bar, they should be taken to the SelectPhotoView()/StoryboardView2, etc...

Furthermore, if they use the mouse to click on one of the tabs in my GUI, the selected item will also need to change accordingly.

Any thoughts on how to implement this would be most welcomed.

Many thanks

import SwiftUI
import UIKit
public struct ContentView6: View {
    @State public var tabSelection = 2  // The app will open on this page.
    public var body: some View {
        TabView(selection: $tabSelection) {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            helpView()
                .tabItem {
                    Image(systemName: "questionmark.circle.fill") // SF symbol
                    Text("Help") // Text beneath symbol
                }
                .tag(0)  // 1st item on menu bar
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            selectPhotoView()
                .tabItem {
                    Image(systemName: "photo") // SF symbol
                    Text("Photos") // Text beneath symbol
                }
                .tag(1)  // 2nd item on menu bar
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            takePictureView()
                .tabItem {
                    Image(systemName: "camera") // SF symbol
                    Text("Camera") // Text beneath symbol
                }
                .tag(2)  // 3rd item on menu bar
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            historyView()
                .tabItem {
                    Image(systemName: "clock") // SF symbol
                    Text("History") // Text beneath symbol
                }
                .tag(3)  // 4th item on menu bar
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            settingsView()
                .tabItem {
                    Image(systemName: "gearshape") // SF symbol
                    Text("Settings") // Text beneath symbol
                }
                .tag(4)  // 5th item on menu bar
        }
    }
}
// Action on 'Help' tab:
struct helpView: View {
    var body: some View {
        ContentView5().edgesIgnoringSafeArea(.all) // Naviagtion Stacks (Help page)
    }
}
// Action on 'Photos' tab:
struct selectPhotoView: View {
    var body: some View {
        storyboardview2().edgesIgnoringSafeArea(.all) // ViewController2 (Photos page)
    }
}
// Action on 'Camera' tab:
struct takePictureView: View {
    var body: some View {
        storyboardview().edgesIgnoringSafeArea(.all) // ViewController (Camera page)
    }
}
// Action on 'History' tab:
struct historyView: View {
    var body: some View {
        //storyboardview3().edgesIgnoringSafeArea(.all) // ViewController3 = OCR - does not belog here (History page)
        storyboardview4().edgesIgnoringSafeArea(.all) // ViewController4 = OCR - does not belog here (History page)
    }
}
// Action on 'Settings' tab:
struct settingsView: View {
    var body: some View {
        //Tutorial().edgesIgnoringSafeArea(.all) // Tutorial - does not belong here (Settings page)
        SettingsView()
    }
}
struct ContentView6_Previews: PreviewProvider {
    static var previews: some View {
        ContentView6()
    }
}

A screenshot of my GUI on Mac is shown below:

I have updated the code for my Touch Bar as shown below. My app successfully runs on iPhone and iPad however on Mac, it fails to run and produces the errors shown in my screenshot.

Any thoughts on how to fix this would be great.

Many thanks.

import UIKit
#if targetEnvironment(macCatalyst)
extension NSTouchBarItem.Identifier {
    static let deleteRecipe = NSTouchBarItem.Identifier("com.example.apple-samplecode.Recipes.deleteRecipe")
    static let editRecipe = NSTouchBarItem.Identifier("com.example.apple-samplecode.Recipes.editRecipe")
    static let toggleRecipeIsFavorite = NSTouchBarItem.Identifier("com.example.apple-samplecode.Recipes.toggleRecipeIsFavorite")
}
extension ViewController2: NSTouchBarDelegate {
    override func makeTouchBar() -> NSTouchBar? {
        let touchBar = NSTouchBar()
        touchBar.delegate = self
        touchBar.defaultItemIdentifiers = [
            .flexibleSpace,
            .deleteRecipe,
            .flexibleSpace,
            .editRecipe,
            .toggleRecipeIsFavorite,
            .flexibleSpace
        ]
        return touchBar
    }
    func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? {
        let touchBarItem: NSTouchBarItem?
        switch identifier {
//        case .deleteRecipe:
//            guard let image = UIImage(systemName: "trash") else { return nil }
//            touchBarItem = NSButtonTouchBarItem(identifier: identifier,
//                                                image: image,
//                                                target: self,
//                                                action: #selector(RecipeDetailViewController.deleteRecipe(_:)))
//
        case .editRecipe:
            guard let image = UIImage(systemName: "square.and.pencil") else { return nil }
            touchBarItem = NSButtonTouchBarItem(identifier: identifier,
                                                image: image,
                                                target: self,
                                                action: #selector(abc(_:)))
//        case .toggleRecipeIsFavorite:
//            guard let recipe = self.recipe else { return nil }
//
//            let name = recipe.isFavorite ? "heart.fill" : "heart"
//            guard let image = UIImage(systemName: name) else { return nil }
//
//            touchBarItem = NSButtonTouchBarItem(identifier: identifier,
//                                                image: image,
//                                                target: self,
//                                                action: #selector(RecipeDetailViewController.toggleFavorite(_:)))
        default:
            touchBarItem = nil
        }
        return touchBarItem
    }
}
// Action on 'Photos' tab:
struct abc: View {
    var body: some View {
        storyboardview2().edgesIgnoringSafeArea(.all) // ViewController2 (Photos page)
    }
}
#endif

Touch Bar
 
 
Q