SwiftUI 更新主菜单 [已解决] kludgey

2024-05-14

真正的问题

你如何更新mainMenu在 SwiftUI 中,它真的可以工作吗?

我在 SwiftUI 中构建了一个基于 MacOS 文档的应用程序,其中包括所有内置的文件菜单命令(即关闭、保存、复制、重命名...等)

在保存文档之前,我会验证结构,并希望在存在任何验证错误时向用户显示模式对话框。

模式对话框只是一个简单的“确定/取消”对话框 - “确定”意味着用户很乐意保存带有验证错误的文件,“取消”则需要停止保存操作。

所以问题是:“如何拦截内置的‘保存’菜单命令来显示此对话框?

我试图覆盖.saveItemCommandGroup - 但这取代了all菜单项,我只想覆盖几个命令(“保存”和“另存为”),并且不想重新实现所有命令(而且我不确定我是否有能力这样做)

        .commands {
            CommandGroup(replacing: .saveItem) {
                // code goes here - but removes all of the in-built menus
            }
        }

我已经尝试过这个解决方案(在 SwiftUI 文档应用程序中,如何从函数内保存文档 https://stackoverflow.com/questions/68522523/in-a-swiftui-document-app-how-to-save-a-document-from-within-a-function)

并将其放入我的 AppDelegate 中

    public func applicationDidBecomeActive(_ notification: Notification) {
        let menu = NSApplication.shared.mainMenu!.items.first(where: { $0.title == "File" })!
        let submenu = menu.submenu!.items.first(where: { $0.title == "Save" })!
        submenu.action = #selector(showDialog)
    }

    @objc func showDialog() {
        var retVal: Int = 0

        let thisWindow: NSWindow? = NSApplication.shared.mainWindow

        let nsAlert: NSAlert = NSAlert()
        let cancelButton: NSButton = nsAlert.addButton(withTitle: "Cancel")
        cancelButton.tag = 1

        let okButton: NSButton = nsAlert.addButton(withTitle: "OK")
        okButton.tag = 0

        // The below code is replaced
        nsAlert.beginSheetModal(for: thisWindow!) { modalResponse in
            print(modalResponse)
            retVal = modalResponse.rawValue


            if retVal == 0 {
                print("save")
            } else {
                print("cancel")
            }
        }
    }

然而它实际上并没有调用showDialog功能。

编辑/更新

我在更新菜单时仍然遇到困难,但在上面的示例中调用beginModalSheet是不正确的,因为该进程将在后台运行。将调用更新为runModal()这将停止写入文件的任何后台进程。

    @objc func showDialog() {
        let nsAlert: NSAlert = NSAlert()
        let cancelButton: NSButton = nsAlert.addButton(withTitle: "Cancel")
        cancelButton.tag = 1

        let okButton: NSButton = nsAlert.addButton(withTitle: "OK")
        okButton.tag = 0

        let response: Int = nsAlert.runModal().rawValue
        if response == 0 {
            print("save")
            NSApp.sendAction(#selector(NSDocument.save(_:)), to: nil, from: nil)
        } else {
            print("cancel")
        }
    }

我在某处读到您需要在窗口出现之前设置菜单,并且我还读到您需要在设置 AppDelegate 之前设置菜单。

另一个编辑

看这个帖子隐藏 SwiftUI / MacOS 应用程序的编辑菜单 https://stackoverflow.com/questions/71309874/hiding-edit-menu-of-a-swiftui-macos-app

和这个评论

Thoughts:SwiftUI 要么有错误,要么他们真的不希望您删除 NSApp.mainMenu 中的顶级菜单。 SwiftUI 似乎重置了整个菜单,目前无法覆盖或自定义大多数细节(Xcode 13.4.1)。 CommandGroup(replacing: .textEditing) { } 式命令不允许您删除或清除整个菜单。当 SwiftUI 需要时,即使您没有指定任何命令,分配一个新的 NSApp.mainMenu 也会被破坏。


XCode 14.1 Swift 5

经过大量超级令人沮丧的搜索尝试和大量代码之后 - 我将问题简化为只是尝试更改名称save菜单项 - 如果我可以做到这一点 - 那么我也可以更改它的操作。

我是这样做的

我的 Tetsing 应用程序名为YikesRedux

Steps:

  1. 注册AppDelegate
  2. 覆盖applicationWillUpdate method
  3. 将菜单更新放在DispatchQueue.main.async closure
  4. 经过几天的搜索,你已经解决了这个问题,喜极而泣

YikesAppRedux.swift

import SwiftUI

@main
struct YikesReduxApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate // <- Don't forget the AppDelegate

    var body: some Scene {
        DocumentGroup(newDocument: YikesReduxDocument()) { file in
            ContentView(document: file.$document)
        }
    }
}

AppDelegate.swift

import Foundation
import AppKit

public class AppDelegate: NSObject, NSApplicationDelegate {
    public func applicationWillUpdate(_ notification: Notification) {
        DispatchQueue.main.async {
            let currentMainMenu = NSApplication.shared.mainMenu

            let fileMenu: NSMenuItem? = currentMainMenu?.item(withTitle: "File")
            if nil != fileMenu {
                let saveMenu = fileMenu?.submenu!.item(withTitle: "Save")
                if nil != saveMenu {
                    print("updated menu")
                    saveMenu?.title = "Save Updated"
                }
            }
        }
    }
}

我认为这有点混乱 - 因为它在每次应用程序更新时运行(虽然不是很多,但当它确实发生时,您可以在控制台“更新菜单”中看到打印输出)

我确实尝试保留一个关于菜单是否更新的状态变量,以尝试不再这样做 - 但在多文档窗口环境中,您需要跟踪每个窗口......(而且 Swift 只会在需要的时候破坏菜单 - 所以它没有达到预期的效果。)

我几乎把菜单更新代码放在我能想到的所有地方

  • 每一个AppDelegate函数覆盖
  • 的初始化方法App, the ContentView
  • 关于文档读取功能/写入功能
  • 你能想到的 - 我把它放在那里(我什至有一个托管控制器,一个 NSViewRepresentable)

然后我将它们一一删除,直到找到解决方案。

如果有一种不那么笨拙的方法来做到这一点,我会很高兴。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SwiftUI 更新主菜单 [已解决] kludgey 的相关文章

  • 为什么选择选择器选项后我的 SwiftUI 页面标题会发生变化?

    struct SettingsView View let settings Setting Setting name Aperture Increments options 1 3 1 2 1 Setting name Shutter Sp
  • UITabBarController 为 TabBar 的每个 ViewController 提供不同的 Storyboard 文件

    我的团队正在开发一个具有 UITabBarController 的应用程序 我们正在使用 Storyboard 来开发界面和流程 由于我们是一个团队 所以我们不能将所有流程放在一个故事板中 因为这会导致与 SVN 同步出现问题 所以 解决方
  • 詹金斯配置文件问题

    检查依赖关系 找不到与 Nitin xxxxxxx xyzCAppStore 匹配的 iOS 配置文件 Xcode 找不到与 Nitin xxxxxxx xyzCAppStore 匹配的配置文件 安装配置文件 通过将其拖放到 Xcode 的
  • 在 Mac 上正确运行基于 SWT 的跨平台 jar

    我一直致力于一个基于 SWT 的项目 该项目旨在部署为 Java Web Start 从而可以在多个平台上使用 到目前为止 我已经成功解决了由于 SWT 依赖的系统特定库而出现的导出问题 请参阅相关thread https stackove
  • Phonegap Build 与 Xcode4 上的 Phonegap 对比?配置.xml?

    有一个使用phonegap构建的应用程序 我已经使用它编译和测试了http build phonegap com http build phonegap com服务 我发现它使用 XCode 的构建方式与在 Phonegap 网站上的构建方
  • 将通配符包标识符转换为单个 ID

    我在应用程序商店中有一个使用通配符包标识符的应用程序 我想实现应用内购买 这需要非通配符ID 如何将现有应用的通配符 ID 转换为静态 ID 以进行应用内购买和推送通知 应用程序的捆绑标识符在更新之间必须始终保持相同 但 AppID 实际上
  • NSSavePanel:压制“确认替换?”对话

    在导航服务领域 人们可以指定kNavDontConfirmReplacement作为创建一个选项NavDialogRef当使用已存在的文件名保存时 不会要求用户确认文件的替换 如何指定与 Cocoa 等效的行为NSSavePanel 具体方
  • 我可以在 macOS 上使用 win32com 客户端吗?

    我一直在研究 Pycel 和 Xlrd 库 在 Mac 上使用它们的问题是这两个库都使用 win32com client 读取 Excel 文件 所以我想知道 有什么办法我可以使用win32commacOS 的客户端 如果没有 我可以使用类
  • 无法在 OSX 上使用 eclipse for android 链接到 cocos2dx

    我以前从来没有花这么多时间来初始设置开发环境 这有点荒谬 我正在尝试运行cocos2dx附带的演示代码 我在用着 ADK 附带的 eclipse 风格 cocos2d 2 1beta3 x 2 1 0 ndk r8c 我尝试使用 creat
  • 如何呈现半屏模态视图?

    我有一个 UIViewController 当按下按钮时 我想要一个半屏视图向上滑动 其中有一个 UIPicker 我在 IB 中使用 UIPicker 和带有 完成 取消 按钮的 UIToolBar 制作了一个 UIView 我怎样才能做
  • 如何在 MAMP 上显示错误?

    我有 MAMP 但我不知道如何在其上显示错误 当我的 php 代码出现错误时 它只显示空白页 我在 Google 上搜索过 我发现我必须在所有文件夹和版本上将其更改为 display errors on 并将其包含在我的页面上 错误报告 E
  • Qt:更改 Mac OS X 上的应用程序 QMenuBar 内容

    我的应用程序对多个 页面 使用 QTabWidget 其中顶级菜单根据用户所在的页面而变化 我的问题是 尝试重新创建菜单栏的内容会导致严重的显示问题 它在除 Mac OS X 之外的所有平台上按预期使用第一种和第三种样式 尚未测试第二种 但
  • 在 CI (Travis/Jenkins) 环境中使用 xcodebuild (Xcode 8) 和自动签名

    随着 Xcode 8 的发布 Apple 引入了一种管理签名配置的新方法 现在你有两个选择Manual and Automatic 根据 WWDC 2016 关于代码签名的会议 WWDC 2016 401 Xcode 应用签名的新增功能 h
  • 添加到 Xcode App 时,Bazel 框架抛出“无法检查应用程序包”

    我正在使用 Bazel 构建基于 MediaPipe 的人脸识别库 我正在使用apple xc框架 https github com bazelbuild rules apple blob master doc rules apple md
  • UI图像位置

    我使用以下代码在 UIView 中放置一些图像 UIImage image UIGraphicsBeginImageContext CGSizeMake 480 320 int k 0 int posY 0 for int i 0 i lt
  • Xcode 6 仪器冻结

    在 Xcode 6 Instruments 中分析我的 iOS 8 应用程序将运行该应用程序约 5 秒 然后冻结 此后探查器仍将运行 但应用程序已冻结且无法使用 发生在设备和模拟器上 无论我使用哪个分析器 计时器 泄漏等 从调试器或临时构建
  • 什么是已弃用的推送转场? (iOS 8)[重复]

    这个问题在这里已经有答案了 我不知道在这种情况下已弃用意味着什么 我是编程新手 正在 Xcode 6 中制作我的前几个应用程序 今天我正在制作一个待办事项列表应用程序 当连接到用户可以输入新待办事项以添加到主表的场景时 我被邀请使用推送转场
  • Docker 容器与主机网络的网络性能非常慢

    我遇到了 Docker 容器和主机网络之间网络性能缓慢的问题 我在 Docker 论坛上提出了这个问题 但到目前为止还没有收到答案 Problem 设置 同一本地网络上的两台 Mac 第一个运行 MQTT 代理 mosquitto 第二个运
  • 在 Swift 中对约束进行动画处理

    我有一个UITextField我想在点击时放大它的宽度 我设置了约束 并确保左侧约束的优先级低于我尝试在右侧设置动画的约束 这是我尝试使用的代码 move the input box UIView animateWithDuration 1
  • 为什么在尝试编译此代码时会收到错误“错误:未知类型名称'虚拟'”?

    Code struct IRenderingEngine virtual void Initialize int width int height 0 virtual void Render const 0 virtual void Upd

随机推荐

  • 虚拟回调接口

    在 Eclipse 为您创建的来自 Google 的示例主从流代码中 片段中包含以下内容 private Callbacks mCallbacks sDummyCallbacks public interface Callbacks pub
  • 连接数组时合并两个 yaml 文档

    我想合并两个 yaml 文档 结果包含 所有映射值 最后一个优先 串联数组 例如给定这个文件 file1 yml animals elephant donkey flavours sour lemon sweet chocolate str
  • 仅当环境变量具有特定值时如何设置 Apache 标头

    我想在我的 Apache 2 4 配置中设置标头 但前提是环境变量具有特定值 SetEnv ENV NAME prod 我如何仅在以下情况下设置此标头ENV NAME is not prod Header set X Robots Tag
  • 如何使用放心的方式在正文中发送 JsonObject 以进行 post 请求?

    我有一个使用 Google Gson 创建的 JsonObject JsonObject jsonObj gson fromJson response1 json JsonElement class getAsJsonObject 我还对现
  • 设置 IRQ 映射

    我正在遵循一些教程和参考文献来尝试设置我的内核 我在教程中遇到了一些不熟悉的代码 但根本没有解释它 这是我被告知映射的代码16 IRQs 0 15 到 ISR 地点32 47 void irq remap void outportb 0x2
  • 哪里可以找到可靠的 K-medoid(不是 k-means)开源软件/工具? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在学习 K medoids 算法 所以如果我提出不恰当的问题 我很抱歉 据我所知 K medoid
  • 我怎么知道我的所有 goroutine 确实正在使用 golang 的同步包等待一个条件

    我有一个应用程序 我正在创建多个 goroutine 来同时执行某个任务 所有工作协程都会等待条件 事件发生 一旦事件被触发 它们就会开始执行 创建完所有goroutines后 主线程在发送广播信号之前应该知道所有goroutines确实处
  • Paypal 付款标准默认输入卡详细信息

    我确信这个主题已经在这里了 但我刚刚与 Paypal 通电话 试图查明他们的帐户上是否有一个设置 可以让客户看到 输入卡详细信息区域 而不是自动 默认设置 引导您登录 注册您的 PayPal 帐户 Paypal 表示没有一个设置可以在他们这
  • 有很多数据库视图可以吗?

    我很少 每月 每季度 使用 Microsoft SQL Server 2005 数据库视图生成数百份 Crystal Reports 报告 在我不读取这些视图的所有时间里 这些视图是否会浪费 CPU 周期和 RAM 因为我很少从视图中读取数
  • IE 中的 Javascript 第 1 行语法错误 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有人能找出这个第 1 行语法错误是什么吗 我正在尝试在 IE6 和 IE7 中进行调试 但找不到问题的根源 http ci elfster
  • WF 和分层状态机

    搜索 bing 和 google 我发现了一些关于与 Windows 工作流程相关的状态图的信息 但令人惊讶的是很少 我得出的唯一明确的答案是 是的 它可以处理状态图 这里有一个教程 但我想确定的是 Does it support hier
  • 循环中的knitr模板和子文档

    圣诞节前我之前问过跨多个 knitr 文档的单一样式表 https stackoverflow com questions 20370584 single style sheet across multiple knitr document
  • 使用 R 读取和转换二进制原始数据

    我有一个file https drive google com file d 0BxMpk0nhnJy6SFhxd2xuMzJYYlk edit usp sharing其中包含原始 二进制数据和 ascii 它包含一个时间戳和一个代表速度的
  • 如何使用特定版本的NPM?

    如何切换我正在使用的 npm 版本 现在 npm v 1 1 65 但我需要 1 0 x 我尝试过 但出现错误 npm version 1 0 npm ERR version No package json found 有人知道如何使用不同
  • C 静态代码分析器

    您使用哪种静态代码分析器 如果有 我一直在 Python 中使用 PyLint 我对它非常满意 现在我需要类似的 C 代码 为了正常的日常使用 您需要抑制多少输出 维基百科维护着一个静态代码分析工具列表 http en wikipedia
  • 监听 redux 动作

    我想创建一个可重用的 redux 表模块 它将存储和更新页码 显示的总页数等 我可以在所有页面之间共享这些模块 但是 我需要更新操作来触发刷新数据操作 该操作将根据页面到达不同的端点 因此 可能类似于页面特定的监听 RefreshData
  • 从 plist 文件中解码数据

    我丢失了在 Macbook Air 上用 Textwrangler 编写的文本文件中的一些数据 我在扩展名为 plist 的文件中找到了其中一些 文件是用 xml 编写的 如下所示
  • 将 Django 部署到 AWS;傻瓜静态文件

    我对这个项目的最后一步完全迷失了 到目前为止 我已经能够开发一个 Django 应用程序 它可以在本地主机上按照我想要的方式工作 我已经能够将网站部署到 AWS EC2 但我一定错过了有关提供静态文件的一些基本知识 我什至还没有尝试过媒体文
  • 使用 proguard 混淆文件名

    我正在使用 proguard 和 Android Studio 混淆我的 apk 当我反编译我的apk时 我可以看到很多文件 例如aaa java aab java ETC 但我项目中的所有文件都有原始名称 有没有办法混淆我的项目的文件名
  • SwiftUI 更新主菜单 [已解决] kludgey

    真正的问题 你如何更新mainMenu在 SwiftUI 中 它真的可以工作吗 我在 SwiftUI 中构建了一个基于 MacOS 文档的应用程序 其中包括所有内置的文件菜单命令 即关闭 保存 复制 重命名 等 在保存文档之前 我会验证结构