SwiftUI macOS 命令(菜单栏)和视图
SwiftUI macOS Commands (menu bar) and View
嗨,我开始学习 SwiftUI 和 macOS 开发。我正在使用 SwiftUI 生命周期。如何从菜单栏的焦点 window 中调用函数。
除了 Apple 文档,我发现 this reference 并且能够使用命令创建菜单项,但我不知道如何从我的视图中调用函数。
例如:
假设这是我的 App 结构:
import SwiftUI
@main
struct ExampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}.commands {
CommandMenu("First menu") {
Button("Action!") {
// How do I call the views action function?
}
}
}
}
这是我的观点:
struct ContentView: View {
public func action() {
print("It works")
}
var body: some View {
Text("Example")
}
}
我刚刚输入了示例代码,抱歉,如果有任何错别字,但我希望你能理解。
因为 SwiftUI 中的 View
s 是瞬态的,你不能持有对 ContentView
的特定实例的引用来调用它的函数。但是,您可以 做的是更改传递给内容视图的部分状态。
例如:
@main
struct ExampleApp: App {
@StateObject var appState = AppState()
var body: some Scene {
WindowGroup {
ContentView(appState: appState)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}.commands {
CommandMenu("First menu") {
Button("Action!") {
appState.textToDisplay = "\(Date())"
}
}
}
}
}
class AppState : ObservableObject {
@Published var textToDisplay = "(not clicked yet)"
}
struct ContentView: View {
@ObservedObject var appState : AppState
var body: some View {
Text(appState.textToDisplay)
}
}
注意.commands
修饰符继续WindowGroup { }
在此示例中,AppState
是一个 ObservableObject
,它保存应用程序的某些状态。它使用参数传递给 ContentView
。您也可以通过环境对象 (https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views)
传递它
单击菜单项时,它会设置 textToDisplay
,即 AppState
上的 @Published
属性。 ContentView
将在更新 AppState
的 @Published 属性 时更新。
这是您要使用的模式的总体思路。如果您有此模式未涵盖的用例,请在评论中告诉我。
根据您的评论进行更新:
import SwiftUI
import Combine
@main
struct ExampleApp: App {
@StateObject var appState = AppState()
var body: some Scene {
WindowGroup {
ContentView(appState: appState)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}.commands {
CommandMenu("First menu") {
Button("Action!") {
appState.textToDisplay = "\(Date())"
}
Button("Change background color") {
appState.contentBackgroundColor = Color.green
}
Button("Toggle view") {
appState.viewShown.toggle()
}
Button("CustomCopy") {
appState.customCopy.send()
}
}
}
}
}
class AppState : ObservableObject {
@Published var textToDisplay = "(not clicked yet)"
@Published var contentBackgroundColor = Color.clear
@Published var viewShown = true
var customCopy = PassthroughSubject<Void,Never>()
}
class ViewModel : ObservableObject {
@Published var text = "The text I have here"
var cancellable : AnyCancellable?
func connect(withAppState appState: AppState) {
cancellable = appState.customCopy.sink(receiveValue: { _ in
print("Do custom copy based on my state: \(self.text) or call a function")
})
}
}
struct ContentView: View {
@ObservedObject var appState : AppState
@State var text = "The text I have here"
@StateObject private var viewModel = ViewModel()
var body: some View {
VStack {
Text(appState.textToDisplay)
.background(appState.contentBackgroundColor)
if appState.viewShown {
Text("Shown?")
}
}
.onReceive(appState.$textToDisplay) { (newText) in
print("Got new text: \(newText)")
}
.onAppear {
viewModel.connect(withAppState: appState)
}
}
}
在我的更新中,您可以看到我已经解决了背景颜色的问题,显示隐藏视图,甚至在其中一个 @Published 属性更改时收到通知(通过 onReceive
) .
您还可以看到我如何使用自定义发布者 (customCopy
) 将操作传递给 ContentView
的 ViewModel
嗨,我开始学习 SwiftUI 和 macOS 开发。我正在使用 SwiftUI 生命周期。如何从菜单栏的焦点 window 中调用函数。
除了 Apple 文档,我发现 this reference 并且能够使用命令创建菜单项,但我不知道如何从我的视图中调用函数。
例如:
假设这是我的 App 结构:
import SwiftUI
@main
struct ExampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}.commands {
CommandMenu("First menu") {
Button("Action!") {
// How do I call the views action function?
}
}
}
}
这是我的观点:
struct ContentView: View {
public func action() {
print("It works")
}
var body: some View {
Text("Example")
}
}
我刚刚输入了示例代码,抱歉,如果有任何错别字,但我希望你能理解。
因为 SwiftUI 中的 View
s 是瞬态的,你不能持有对 ContentView
的特定实例的引用来调用它的函数。但是,您可以 做的是更改传递给内容视图的部分状态。
例如:
@main
struct ExampleApp: App {
@StateObject var appState = AppState()
var body: some Scene {
WindowGroup {
ContentView(appState: appState)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}.commands {
CommandMenu("First menu") {
Button("Action!") {
appState.textToDisplay = "\(Date())"
}
}
}
}
}
class AppState : ObservableObject {
@Published var textToDisplay = "(not clicked yet)"
}
struct ContentView: View {
@ObservedObject var appState : AppState
var body: some View {
Text(appState.textToDisplay)
}
}
注意.commands
修饰符继续WindowGroup { }
在此示例中,AppState
是一个 ObservableObject
,它保存应用程序的某些状态。它使用参数传递给 ContentView
。您也可以通过环境对象 (https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views)
单击菜单项时,它会设置 textToDisplay
,即 AppState
上的 @Published
属性。 ContentView
将在更新 AppState
的 @Published 属性 时更新。
这是您要使用的模式的总体思路。如果您有此模式未涵盖的用例,请在评论中告诉我。
根据您的评论进行更新:
import SwiftUI
import Combine
@main
struct ExampleApp: App {
@StateObject var appState = AppState()
var body: some Scene {
WindowGroup {
ContentView(appState: appState)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}.commands {
CommandMenu("First menu") {
Button("Action!") {
appState.textToDisplay = "\(Date())"
}
Button("Change background color") {
appState.contentBackgroundColor = Color.green
}
Button("Toggle view") {
appState.viewShown.toggle()
}
Button("CustomCopy") {
appState.customCopy.send()
}
}
}
}
}
class AppState : ObservableObject {
@Published var textToDisplay = "(not clicked yet)"
@Published var contentBackgroundColor = Color.clear
@Published var viewShown = true
var customCopy = PassthroughSubject<Void,Never>()
}
class ViewModel : ObservableObject {
@Published var text = "The text I have here"
var cancellable : AnyCancellable?
func connect(withAppState appState: AppState) {
cancellable = appState.customCopy.sink(receiveValue: { _ in
print("Do custom copy based on my state: \(self.text) or call a function")
})
}
}
struct ContentView: View {
@ObservedObject var appState : AppState
@State var text = "The text I have here"
@StateObject private var viewModel = ViewModel()
var body: some View {
VStack {
Text(appState.textToDisplay)
.background(appState.contentBackgroundColor)
if appState.viewShown {
Text("Shown?")
}
}
.onReceive(appState.$textToDisplay) { (newText) in
print("Got new text: \(newText)")
}
.onAppear {
viewModel.connect(withAppState: appState)
}
}
}
在我的更新中,您可以看到我已经解决了背景颜色的问题,显示隐藏视图,甚至在其中一个 @Published 属性更改时收到通知(通过 onReceive
) .
您还可以看到我如何使用自定义发布者 (customCopy
) 将操作传递给 ContentView
的 ViewModel