【问题标题】:Passing a Value from App to ContentView in SwiftUI在 SwiftUI 中将值从 App 传递到 ContentView
【发布时间】:2022-01-08 03:23:00
【问题描述】:

我找到了很多关于如何让用户选择菜单项然后打开文件夹的资源。以下是我所拥有的。

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
    }
}

好的。那没问题。我可以打印文件路径。好吧,我的实际问题是如何将此值返回给ContentView?是ContentView 在此示例应用程序中虚拟运行该节目。所以我使用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 不会更新。那么如何让ContentView 接收来自App 的菜单调用的值?谢谢。

【问题讨论】:

    标签: macos swiftui observable menuitem


    【解决方案1】:

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

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

    @ObservedObject var menuObservable : MenuObservable
    

    在你的Oh_My_App:

    WindowGroup {
        ContentView(menuObservable: menuObservable)
    }
    

    【讨论】:

    • 非常感谢。我想我是在正确的方向。或者......您会这样做以将值返回给ContentView吗?
    • 是的,这绝对是我用来与ContentView 共享状态的方法(我假设您的意思是“将值返回给...”)。
    猜你喜欢
    • 1970-01-01
    • 2020-09-05
    • 1970-01-01
    • 2021-05-18
    • 2019-12-28
    • 2020-06-20
    • 2021-03-05
    • 2021-02-26
    • 1970-01-01
    相关资源
    最近更新 更多