在 SwiftUI 中将值从 App 传递到 ContentView

Passing a Value from App to ContentView in SwiftUI

我找到了很多关于如何让用户 select 一个菜单项然后打开一个文件夹的资源。以下是我的。

import SwiftUI

@main
struct Oh_My_App: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .frame(width: 480.0, height: 320.0)
        }.commands {
            CommandGroup(after: .newItem) {
                Button {
                    if let url = showFileOpenPanel() {
                        print(url.path)
                    }
                } label: {
                    Text("Open file...")
                }
                .keyboardShortcut("O")
            }
        }
    }
    
    func showFileOpenPanel() -> URL? {
        let openPanel = NSOpenPanel()
        openPanel.canChooseDirectories = true
        openPanel.canCreateDirectories = false
        openPanel.canChooseFiles = false
        openPanel.title = "Selecting a folder..."
        openPanel.message = "Please select a folder containing one or more files."
        let response = openPanel.runModal()
        return response == .OK ? openPanel.url : nil
    }
}

好的。那没问题。我可以打印文件路径。那么,我的实际问题是如何将此值 return 变为 ContentViewContentView 实际上是此示例应用程序中的显示 运行。所以我使用 ObservableObject 如下。

import SwiftUI

@main
struct Oh_My_App: App {
    @StateObject var menuObservable = MenuObservable()
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }.commands {
            CommandGroup(after: .newItem) {
                Button {
                    menuObservable.openFile()
                } label: {
                    Text("Open file...")
                }
                .keyboardShortcut("O")
            }
        }
    }
}

class MenuObservable: ObservableObject {
    @Published var fileURL: URL = URL(fileURLWithPath: "")
    func openFile() {
        if let openURL = showFileOpenPanel() {
            fileURL = openURL
        }
    }
    
    func showFileOpenPanel() -> URL? {
        let openPanel = NSOpenPanel()
        openPanel.canChooseDirectories = true
        openPanel.canCreateDirectories = false
        openPanel.canChooseFiles = false
        openPanel.title = "Selecting a folder..."
        openPanel.message = "Please select a folder containing one or more files."
        let response = openPanel.runModal()
        return response == .OK ? openPanel.url : nil
    }
}
// ContentView.swift //
import SwiftUI

struct ContentView: View {
    @ObservedObject var menuObservable = MenuObservable()
    @State var filePath: String = ""
    
    var body: some View {
        ZStack {
            VStack {
                Text("Hello: \(filePath)")
            }.onChange(of: menuObservable.fileURL) { newValue in
                filePath = newValue.path
            }
        }
    }
}

我的 ContentView 不会更新。那么如何让 ContentViewApp 的菜单调用中接收值?谢谢。

现在,您正在 ContentView 中创建 MenuObservable 新实例 ,因此它与收到菜单命令。您需要传递对现有实例的引用(即 Oh_My_App 拥有的实例)。

在您的 ContentView 中,将 @ObservedObject var menuObservable = MenuObservable() 更改为:

@ObservedObject var menuObservable : MenuObservable

在你的 Oh_My_App 中:

WindowGroup {
    ContentView(menuObservable: menuObservable)
}