如何在 macOS 的 SwiftUI 中使用菜单命令实现多窗口?

2023-11-27

情况

实现一个多窗口应用程序,其中每个窗口都有自己的状态。

Example

这是一个例子(在 github 上)来展示问题:

import SwiftUI

@main
struct multi_window_menuApp: App {

  var body: some Scene {
    WindowGroup {
      ContentView()
    }.commands {
      MenuCommands()
    }
  }
}

struct ContentView: View {
  @StateObject var viewModel: ViewModel  = ViewModel()
  
  var body: some View {
    TextField("", text: $viewModel.inputText)
      .disabled(true)
      .padding()
  }
}

public class ViewModel: ObservableObject {
  
  @Published var inputText: String = "" {
    didSet {
      print("content was updated...")
    }
  }
}

Question

我们应该如何以编程方式找出当前选定的视图是什么,以便我们可以在菜单命令即将完成时更新状态并更新视图模型中的状态?

import Foundation
import SwiftUI
import Combine

struct MenuCommands: Commands {
  
  var body: some Commands {
    CommandGroup(after: CommandGroupPlacement.newItem, addition: {
      Divider()
      Button(action: {
        let dialog = NSOpenPanel();
        
        dialog.title = "Choose a file";
        dialog.showsResizeIndicator = true;
        dialog.showsHiddenFiles = false;
        dialog.allowsMultipleSelection = false;
        dialog.canChooseDirectories = false;
        
        if (dialog.runModal() ==  NSApplication.ModalResponse.OK) {
          let result = dialog.url
          if (result != nil) {
            let path: String = result!.path
            do {
              let string = try String(contentsOf: URL(fileURLWithPath: path), encoding: .utf8)
              print(string)
              // how to get access to the currently active view model to update the inputText variable?
              // viewModel.inputText = string
            }
            catch {
              print("Error \(error)")
            }
          }
        } else {
          return
        }
      }, label: {
        Text("Open File")
      })
      .keyboardShortcut("O", modifiers: .command)
    })
  }
}

可能有助于解决这个问题的链接:

  • http://www.gfrigerio.com/build-a-macos-app-with-swiftui/
  • https://troz.net/post/2021/swiftui_mac_menus/
  • https://onmyway133.com/posts/how-to-manage-windowgroup-in-swiftui-for-macos/

我在解决类似问题时遇到了这个问题。我相信 SwiftUI 的方法是使用FocusedValue:

// create an active viewmodel key
struct ActiveViewModelKey: FocusedValueKey {
  typealias Value = ViewModel
}

extension FocusedValues {
  var activeViewModel: ViewModel? {
    get { self[ActiveViewModelKey.self] }
    set { self[ActiveViewModelKey.self] = newValue }
  }
}

struct ContentView: View {
  @StateObject var viewModel: ViewModel  = ViewModel()
  
  var body: some View {
    TextField("", text: $viewModel.inputText)
      ...
      .focusedSceneValue(\.activeViewModel, viewModel) // inject the focused value
  }
}

struct MenuCommands: Commands {
  @FocusedValue(\.activeViewModel) var activeViewModel // inject the active viewmodel
  
  var body: some Commands {
    CommandGroup(after: CommandGroupPlacement.newItem, addition: {
      Divider()
      Button(action: {
        ...
        activeViewModel?.inputText = string
      }, label: {
        Text("Open File")
      })
      .keyboardShortcut("O", modifiers: [.command])
    })
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 macOS 的 SwiftUI 中使用菜单命令实现多窗口? 的相关文章

随机推荐

  • TextView旋转保持宽度和高度

    我试图旋转文本视图 但是当我旋转它时 它会保留宽度和高度信息 我想要所选区域消失我只想文本出现在居中对齐的绿色指示器上 我正在更改java部分中的文本 小文本 但是当文本的长度发生变化时 对齐方式会变得疯狂 图3 这是我的代码我做错了什么
  • 访问日志中的奇怪请求导致IllegalArgumentException

    我使用 tomcat8 0 43 作为我的服务器 在查看我的日志时 有时我会看到 信息 org apache coyote http11 AbstractHttp11Processor process 解析 HTTP 请求标头时出错注意 H
  • 类型错误:$(...)[1].attr 不是函数

    我的链接设置如下 HTML a href www example1 com class some link a href www example2 com class some link a href www example3 com cl
  • SwipeRefreshLayout 阻止水平滚动 RecyclerView

    我的设置很简单
  • 将标签移动到饼图中间

    我的饼图可以正常工作 但我注意到实际图表的文本框似乎无法正常工作 它们只是聚集在一起 所以我想知道是否有什么方法可以将标签移到白色圆圈所在的中间 并在其旁边有匹配的颜色 crimeTypes dict crimeData Crime typ
  • 抽象类的集合(或类似的东西......)

    场景 我正在用 Java 编写一个涉及汽车的程序 注意 我 尽我所能 简化了这个场景 使其更通用且更容易理解 我实际上并不是在和汽车打交道 我创建了一个Cars类 它是一个集合Car对象 The Car对象有一个speed 双 和一个yea
  • Google Place API - 始终返回此“状态”:“REQUEST_DENIED”

    我目前正在使用 Google Place API 每当我要访问此链接时都会遇到问题 输入如下信息纬度 经度 and API key并设置传感器等于假 但它总是显示 debug info html attributions results s
  • python 套接字挂在连接上

    我正在尝试使用套接字模块在 python 中创建透明代理 但由于某种原因 它挂在 connect 套接字上 这是我正在使用的代码 from future import division import socket import struct
  • 如何生成 Swagger codegen Java 模型作为 JPA 实体

    我正在使用 Swagger codegen 创建要在 Spring REST 服务器中使用的 Java 模型 并且想知道如何让 Swagger 将每个模型声明为 JPA 实体 我用以下代码生成代码swagger codegen maven
  • 如何修改此 t-sql 查询以返回不同列名的最大值?

    我有以下查询 SELECT Rate RateMon RateTue RateWed RateThu RateFri RateSat RateSun FROM Room WHERE Id Id 我只想返回 而不是返回所有列Rate以及 Ra
  • C++ 中的电子邮件验证

    好的 我正在尝试制作一个允许用户输入电子邮件的程序 如果满足两个条件 他们的电子邮件将被视为有效 A 其中必须有一个 符号 B 后面必须有一个句点 我把大部分代码都写下来了 但是在验证 符号之前有句点的电子邮件时 我遇到了一些困难 如果它们
  • 通过 App Delegate 的 UITabBarController 检测何时按下 tabBar 项目

    我知道这个问题已经被问过几次了 但当我有我的资料时 我仍然坚持这个问题UITabBarController in my AppDelegateclass 和 viewControllers 仅设置为 self tabBarControlle
  • 无法在 Windows 上安装 python Polyglot 包

    我正在尝试使用以下命令安装 Polyglot 包 pip install polyglot 我收到以下信息 Collecting polyglot Using cached polyglot 15 10 03 py2 py3 none an
  • 你能举一个C++中堆栈溢出的例子吗?

    你能举一个C 中堆栈溢出的例子吗 不涉及无限递归的典型情况是在堆栈上声明太大的自动变量 例如 int foo int array 1000000
  • 在 PHP 类中使用外部变量

    我对 PHP 课程非常陌生 所以如果答案真的很明显 请原谅我 我试图弄清楚如何在类内部使用类外部定义的变量 这是一个非常粗略的例子 myVar value class myClass private class var myVar REST
  • MySQL 错误 1045,“用户 'user'@'localhost' 的访问被拒绝(使用密码:YES)”

    这个问题似乎被问了很多 但我找不到明确的答案 我正在使用 MySQL 进行一些 webapp 测试 一开始我使用 root 用户 具有非空密码 我的 root 用户在应用程序 通过 PHP 和 Python 的 Django 测试 命令行以
  • 获取/使用 Firebase JWT

    很早就接触了 Firebase 文档 到目前为止非常喜欢它 作为 n00b 这里有一个概念性问题 Firebase 身份验证生成的 JWT 令牌是否可以在客户端访问 我想打电话给一些人external服务并希望利用 JWT 作为安全机制 所
  • 如何生成有效的 ECDSA EC 密钥对?

    我正在尝试在 Android 中使用 SpongyCastle 生成 ECDSA 密钥对 这是代码 static Security insertProviderAt new org spongycastle jce provider Bou
  • catalina.bat 开始不工作

    由于某些奇怪的原因 我在启动 tomcat 时遇到问题 它曾经 之前启动没有问题 错误太长 无法复制 完全从命令提示符 有人知道可能出了什么问题吗 C apache tomcat 7 0 8 bin gt catalina bat star
  • 如何在 macOS 的 SwiftUI 中使用菜单命令实现多窗口?

    情况 实现一个多窗口应用程序 其中每个窗口都有自己的状态 Example 这是一个例子 在 github 上 来展示问题 import SwiftUI main struct multi window menuApp App var bod