让 SwiftUI 应用出现在 macOS Dock 中

Posted

技术标签:

【中文标题】让 SwiftUI 应用出现在 macOS Dock 中【英文标题】:Make SwiftUI app appear in the macOS Dock 【发布时间】:2021-08-22 19:24:14 【问题描述】:

我是 macOS UI 编程的菜鸟。上次我这样做是在 20 世纪的某个时候,使用 Visual Mac Standard Basic 或 REALbasic……

我正在尝试构建一个图形 UI,以与使用 SwiftUI 以 Swift 编写的一些算法进行交互。我不打算分发可运行的应用程序包,而是应该使用swift run 或类似命令从命令行启动 GUI。

我设法在屏幕上显示了我的 UI 的窗口,但它并没有真正发挥作用。从命令行运行可执行文件并单击窗口使其看起来像最前面的窗口时,它不会获得焦点,但 Terminal.app 的窗口仍然具有焦点并接收击键。 Dock 中没有应用程序图标(即使是通用图标),我无法使用 Command-Tab 切换到应用程序。

在这方面从应用程序中获得通常的行为我缺少什么?

我使用的是 macOS 10.15.7 和 Xcode 12.4。我希望从命令行使用 Swift Package Manager 构建应用程序。以下是我正在处理的最小项目中的文件:

Package.swift
// swift-tools-version:5.3
import PackageDescription

let linkerFlags = [
    "-Xlinker", "-sectcreate",
    "-Xlinker", "__TEXT",
    "-Xlinker", "__info_plist",
    "-Xlinker", "Resources/Info.plist"]

let package = Package(
    name: "ConnectedRegions",
    platforms: [.macOS(.v10_15)],
    products: [
        .executable(name: "ConnectedRegions", targets: ["ConnectedRegions"])],
    targets: [
        .target(
            name: "ConnectedRegions",
            linkerSettings: [.unsafeFlags(linkerFlags)])])
Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSPrincipalClass</key>
    <string>NSApplication</string>
</dict>
</plist>
main.swift
import Cocoa
import SwiftUI

class AppDelegate: NSObject, NSApplicationDelegate 
    func applicationDidFinishLaunching(_ notification: Notification) 
        let window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 200, height: 200),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered,
            defer: false)
        
        window.center()
        window.contentView = NSHostingView(rootView: Text("Hello").padding(50))
        window.makeKeyAndOrderFront(nil)
    


let delegate = AppDelegate()
NSApplication.shared.delegate = delegate

_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)

【问题讨论】:

我建议在 Xcode 中使用 SwiftUI 创建一个 macOS 应用程序项目,并将您现有的代码添加到该项目中。 【参考方案1】:

使用来自 macOS 11 中 SwiftUI 的新 App 协议,它提供了一个入口点,这很容易实现。无需 Info.plist 即可获得默认菜单和 Dock 图标:

import SwiftUI

@main
struct MyApp: App 
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene 
        WindowGroup 
            VStack 
                Button("Done")  exit(0) 
            
            .padding(100)
        
    


class AppDelegate: NSObject, NSApplicationDelegate 
    func applicationDidFinishLaunching(_ notification: Notification) 
        NSApplication.shared.setActivationPolicy(.regular)
        NSApplication.shared.activate(ignoringOtherApps: true)
    

【讨论】:

以上是关于让 SwiftUI 应用出现在 macOS Dock 中的主要内容,如果未能解决你的问题,请参考以下文章

如何让 SwiftUI SidebarMenu 每次都显示相同的 DetailView 而不是创建一个新的(在 macOS 上)

如何在 SwiftUI macOS 中创建第一响应者

让我们在 MacOS AppKit 上的 SwiftUI 中使用所有可用宽度的按钮

更改内容顺序时,SwiftUI MacOS 列表布局出现故障

SwiftUI:如何在 macOS 应用程序中实现编辑菜单

SwiftUI:响应 macOS 上的应用程序终止