SwiftUI kullanarak bir macOS uygulamasına nasıl araç çubuğu ekleyebilirim?


11

SwiftUI kullanarak bir macOS uygulamasına başlık çubuğunun içinde bir araç çubuğu eklemeye çalışıyorum, aşağıda gösterilene benzer bir şey.

MacOS uygulamasında başlık çubuğundaki araç çubuğu

SwiftUI kullanarak bunu başarmanın bir yolunu bulamıyorum. Şu anda, görünümümün içinde araç çubuğum var (sadece bir metin alanı var), ancak başlık çubuğuna taşımak istiyorum.

Mevcut kodum:

struct TestView: View {
    var body: some View {
        VStack {
            TextField("Placeholder", text: .constant("")).padding()
            Spacer()
        }
    }
}

Yani, benim durumumda, araç çubuğunun içinde metin alanına ihtiyacım var.


MacOS hedefinde SwiftUI hakkında konuşuyorum.
Bijoy Thangaraj

Hayır, navigationBarTitle değiştirici macOS SwiftUI'de mevcut değildir.
Bijoy Thangaraj

Araç Çubuğu şimdilik SwiftUI'de desteklenmiyor. Gerçekten birine ihtiyacınız varsa (neden?) O zaman AppKit'den birini kullanın, hala orada ... gerçekten.
Asperi

@Asperi Bunu yapabildim - lütfen aşağıdaki cevaba bakınız. Araç çubukları (veya başlık çubuğu aksesuarları) macOS uygulamalarında hala yaygın olarak kullanılmaktadır, değil mi?
Bijoy Thangaraj

@Asperi AppKit'ten birini kullanmak için NSToolbar için NSViewRepresentable kullanmak mı demek istediniz? Eğer öyleyse, bu yöntemi denedim ama başarılı olamadım. Bu şekilde bir çözümünüz varsa, bunu kontrol etmek isterim.
Bijoy Thangaraj

Yanıtlar:


6

Yaklaşım 1:

Bu, başlık çubuğu aksesuarı eklenerek yapılır. Bunu AppDelegate.swift dosyasını değiştirerek halledebildim. Doğru görünmesi için biraz tuhaf dolgu uygulamak zorunda kaldım.

AppDelegate.swift

func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()

        // Create the titlebar accessory
        let titlebarAccessoryView = TitlebarAccessory().padding([.top, .leading, .trailing], 16.0).padding(.bottom,-8.0).edgesIgnoringSafeArea(.top)

        let accessoryHostingView = NSHostingView(rootView:titlebarAccessoryView)
        accessoryHostingView.frame.size = accessoryHostingView.fittingSize

        let titlebarAccessory = NSTitlebarAccessoryViewController()
        titlebarAccessory.view = accessoryHostingView       

        // Create the window and set the content view. 
        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.center()
        window.setFrameAutosaveName("Main Window")

        // Add the titlebar accessory
        window.addTitlebarAccessoryViewController(titlebarAccessory)

        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)
    }

TitlebarAccessory.swift

import SwiftUI

struct TitlebarAccessory: View {
    var body: some View {

        TextField("Placeholder", text: .constant(""))

    }
}

Sonuç:

MacOS araç çubuğundaki içerik

Yaklaşım 2 (Alternatif yöntem):

Buradaki fikir, araç çubuğu bölümünü storyboard kullanarak ve uygulamanın geri kalanını SwiftUI kullanarak yapmaktır. Bu, kullanıcı arayüzü olarak film şeridi ile yeni bir uygulama oluşturularak yapılır. Ardından film şeridine gidin ve varsayılan Görünüm Denetleyicisini silin ve yeni bir tane ekleyin NSHostingController. Yeni eklenen Hosting Denetleyicisini ilişkisini ayarlayarak ana pencereye bağlayın. Arabirim oluşturucuyu kullanarak araç çubuğunuzu pencereye ekleyin.

Film şeridi yapılandırması

Kendinize özel bir sınıf ekleyin NSHostingControllerve SwiftUI görünümünüzü bu klasöre yükleyin.

Aşağıdaki örnek kod:

import Cocoa
import SwiftUI

class HostingController: NSHostingController<SwiftUIView> {

    @objc required dynamic init?(coder: NSCoder) {
        super.init(coder: coder, rootView: SwiftUIView())       

    }

}

Bu yaklaşımı kullanmak size araç çubuğunu özelleştirebilmenizi de sağlar.


Sağ tıklayıp "Araç Çubuğunu Özelleştir" i seçerek düzenlenebilir hale getirmenin bir yolu var mı? (Finder, Pages vb. Gibi)
sqwk

2
İlk çözümle hayır. Ancak, yukarıdaki yanıtıma eklediğim alternatif yaklaşıma bakın. Bu şekilde, araç çubuğunu özelleştirme seçeneği sunulur.
Bijoy Thangaraj

@BijoyThangaraj araç çubuğundaki bir düğmeyi kullanarak Statedeğişkenleri nasıl değiştirebilirim SwiftUIView? Denedim ama devlet değişmiyor.
Alan

@Alan, bunu yapmanın bir yolu, WindowController'ınızdan HostingController'ınızda gözlemleyebileceğiniz bir bildirim göndermektir. HostingController'ınızda, bir ObservableObject tutabilir ve alınan bildirime göre özelliklerini değiştirebilirsiniz. Son olarak, bu gözlemlenebilir nesneyi SwiftUIView cihazınıza şu şekilde aktarabilirsiniz:super.init(coder: coder, rootView: AnyView(SwiftUIView().environmentObject(myObservableObject)))
Bijoy Thangaraj

1

UIKit + Katalizör

https://developer.apple.com/documentation/uikit/uititlebar

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        guard let windowScene = (scene as? UIWindowScene) else { return }
        let window = UIWindow(windowScene: windowScene)

        if let titlebar = windowScene.titlebar {

            //toolbar
            let identifier = NSToolbar.Identifier(toolbarIdentifier)
            let toolbar = NSToolbar(identifier: identifier)
            toolbar.allowsUserCustomization = true
            toolbar.centeredItemIdentifier = NSToolbarItem.Identifier(rawValue: centerToolbarIdentifier)
            titlebar.toolbar = toolbar
            titlebar.toolbar?.delegate = self

            titlebar.titleVisibility = .hidden
            titlebar.autoHidesToolbarInFullScreen = true
        }

        window.makeKeyAndVisible()

    }
#if targetEnvironment(macCatalyst)
let toolbarIdentifier = "com.example.apple-samplecode.toolbar"
let centerToolbarIdentifier = "com.example.apple-samplecode.centerToolbar"
let addToolbarIdentifier = "com.example.apple-samplecode.add"

extension SceneDelegate: NSToolbarDelegate {

    func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
        if itemIdentifier == NSToolbarItem.Identifier(rawValue: toolbarIdentifier) {
            let group = NSToolbarItemGroup(itemIdentifier: NSToolbarItem.Identifier(rawValue: toolbarIdentifier), titles: ["Solver", "Resistance", "Settings"], selectionMode: .selectOne, labels: ["section1", "section2", "section3"], target: self, action: #selector(toolbarGroupSelectionChanged))

            group.setSelected(true, at: 0)

            return group
        }

        if itemIdentifier == NSToolbarItem.Identifier(rawValue: centerToolbarIdentifier) {
            let group = NSToolbarItemGroup(itemIdentifier: NSToolbarItem.Identifier(rawValue: centerToolbarIdentifier), titles: ["Solver1", "Resistance1", "Settings1"], selectionMode: .selectOne, labels: ["section1", "section2", "section3"], target: self, action: #selector(toolbarGroupSelectionChanged))

            group.setSelected(true, at: 0)

            return group
        }

        if itemIdentifier == NSToolbarItem.Identifier(rawValue: addToolbarIdentifier) {
            let barButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.add, target: self, action: #selector(self.add(sender:)))
            let button = NSToolbarItem(itemIdentifier: itemIdentifier, barButtonItem: barButtonItem)
            return button
        }

        return nil
    }

    @objc func toolbarGroupSelectionChanged(sender: NSToolbarItemGroup) {
        print("selection changed to index: \(sender.selectedIndex)")
    }

    @objc func add(sender: UIBarButtonItem) {
        print("add clicked")
    }

    func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        [NSToolbarItem.Identifier(rawValue: toolbarIdentifier), NSToolbarItem.Identifier(rawValue: centerToolbarIdentifier), NSToolbarItem.Identifier.flexibleSpace,
            NSToolbarItem.Identifier(rawValue: addToolbarIdentifier),
            NSToolbarItem.Identifier(rawValue: addToolbarIdentifier)]
    }

    func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        self.toolbarDefaultItemIdentifiers(toolbar)
    }

}
#endif
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.