# Mac 应用 Guideline 4 拒审:关掉主窗口后没法再打开 > Mac 应用关掉主窗口后,如果菜单里没有任何一项能把它找回来,Apple 会按 Guideline 4(设计)拒审。SwiftUI 和 AppKit 应用为什么会落到这一步、Apple 建议的两种改法,以及一个 30 秒自测。 - Canonical page: https://obelisk.club/blog/app-review-guideline-4-mac-window-reopen-zh - Author: Peter Zhang - Published: 2026-10-30 - Tags: app-review, app-store, guideline-4, mac, swiftui, appkit, rejection, indie, 中文 被 **Guideline 4(Design)** 拒审、信里写着“没有菜单项可以重新打开”主窗口,意思是审核员关掉了你 Mac 应用的窗口,应用还在运行,却没法从菜单栏把窗口找回来。修法二选一:加一个能重新打开窗口的菜单项(“窗口”菜单里的一项,或改用 SwiftUI 的 `Window` 场景);如果是单窗口应用,也可以在关窗时保存数据并退出。 这种拒审只会发生在 Mac 上,我们自己的 Mac 小工具就收到过,所以提交 Mac 版之前,值得亲手关一次窗口,找找回去的路。如果信里还引用了别的条款,可以把拒信粘贴到 [App 审核拒信解读](/tools/app-review-rejection-decoder),逐条看。 ## Apple 怎么说 Apple 的原文是:"when the user closes the main application window there is no menu item to re-open it"(用户关掉主窗口后,没有菜单项可以重新打开它)。Apple 给了两条出路: - "implement a Window menu that lists the main window so it can be reopened, or provide similar functionality in another menu item"(实现一个列出主窗口的“窗口”菜单,让它能被重新打开,或在别的菜单项里提供类似功能); - "if the application is a single-window app, it might be appropriate to save data and quit the app when the main window is closed"(如果是单窗口应用,可以在主窗口关闭时保存数据并退出)。 ## 为什么会这样 **SwiftUI。** 主场景用的是 `WindowGroup` 时,Apple 文档写明应用 "continues to run even after closing all of its windows"(关掉所有窗口后仍继续运行)。“窗口”菜单只列出*已打开*的窗口,⌘W 之后它就从菜单里消失了。菜单里唯一的回路是“文件 > 新建”,它会从这个窗口组新开一个窗口;而有些单窗口应用觉得“新建”没意义,用 `CommandGroup(replacing: .newItem) { }` 把它删了,于是一条菜单回路都不剩。 **AppKit。** 除非 app delegate 在 `applicationShouldTerminateAfterLastWindowClosed(_:)` 里返回 `true`,否则最后一个窗口关掉后应用会继续运行。如果菜单里没有东西能把窗口叫回来,就是同样的死胡同。如果窗口是你在 Swift 代码里自己创建的,还要把 `isReleasedWhenClosed` 设为 `false`(Apple 文档说明 Swift 和 ARC 代码需要这么做;`NSWindow` 默认是 `true`),并持有一个强引用,这样同一个窗口才能再次显示。 ## 怎么改 **SwiftUI 单窗口应用:改用 `Window` 场景。** Apple 文档说,“窗口”菜单本身就会列出这类单例窗口;并且 "if your app uses a single window as its primary scene, the app quits when the window closes"(如果应用以单个窗口作为主场景,关闭窗口时应用会退出)。这一改同时满足了 Apple 的两条建议。注意关窗口就等于退出,所以用户的改动要随时保存。 ```swift @main struct NotesApp: App { var body: some Scene { Window("Notes", id: "main") { ContentView() } } } ``` **SwiftUI 保留 `WindowGroup`、关窗即退出:** 用 `@NSApplicationDelegateAdaptor` 接一个 app delegate,在 `applicationShouldTerminateAfterLastWindowClosed(_:)` 里返回 `true`。或者干脆保留“文件 > 新建”,不要把 `.newItem` 替换成空。 **AppKit:** 要么保存后关窗即退出: ```swift func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { true } ``` 要么让窗口一直存活,并给它一条回路。在“窗口”菜单里加一项,动作里调用 `mainWindow.makeKeyAndOrderFront(nil)`(比如用 `NSApp.windowsMenu?.addItem(withTitle:action:keyEquivalent:)` 添加),同时处理点击 Dock 图标: ```swift func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool { if !flag { mainWindow.makeKeyAndOrderFront(nil) } return true } ``` 应用已在运行时,用户点 Dock 图标或在访达里再次双击应用,AppKit 就会调用这个方法。点 Dock 能找回窗口只是锦上添花;Apple 的原文要的是**菜单项**,不要只交一个 Dock 处理就去重提。 ## 常见问题 ### Mac 应用关掉主窗口后没有菜单项能重新打开,怎么改? 给用户一个能把窗口叫回来的菜单项,比如在“窗口”菜单里加一项,动作里调用 `makeKeyAndOrderFront`;或者在主窗口关闭时保存数据并退出。Apple 的信里给的就是这两条出路。 ### SwiftUI 的 Mac 应用怎么让主窗口能重新打开? 单窗口应用改用 `Window` 场景代替 `WindowGroup`:“窗口”菜单会列出它,关窗时应用会退出。保留 `WindowGroup` 的话,要么在 `applicationShouldTerminateAfterLastWindowClosed(_:)` 里返回 `true`,要么保留“文件 > 新建”。 ### Mac 应用关掉最后一个窗口时应该退出吗? 单窗口应用可以。Apple 的信里说,主窗口关闭时保存数据并退出可能是合适的做法。AppKit 里在 `applicationShouldTerminateAfterLastWindowClosed(_:)` 返回 `true`,并先保存用户的改动。 ### 点 Dock 图标能找回窗口,审核就能过吗? 不够。用 `applicationShouldHandleReopen` 处理 Dock 点击只是锦上添花,Apple 的原文要的是菜单项,不要只交一个 Dock 处理就去重提。 ## 30 秒自测 启动应用,按 ⌘W,然后只用菜单栏找回窗口:“窗口”菜单、“文件”菜单、应用菜单都看一遍。要么应用已经退出(而且改动已保存),要么某个菜单项能重新打开窗口。两样都不是,审核员也会发现同样的问题。最后再点一下 Dock 图标,确认窗口能回来。 Mac 独有的其他规则见 [2.4.5:沙盒存文件与更新检查](/blog/app-review-guideline-2-4-5-mac-app-store-zh)。更完整的上架前检查见 [2.1 应用完整性](/blog/app-review-guideline-2-1-app-completeness-rejection-zh) 和 [工具箱页面](/toolkit)。 *以上来自 Obelisk Club 自己的送审记录。Apple 的措辞和 API 会变,请以当前 App Review 指南和 Apple 文档为准。*