You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS中如何将运行中的应用添加至Picker视图?

解决SwiftUI Picker遍历运行中应用的编译错误

问题根源

你遇到的编译错误,核心原因有三个:

  • NSWorkspace.shared.runningApplications 返回的 [NSRunningApplication] 元素未遵循 Identifiable 协议,ForEach无法自动识别唯一标识
  • 在Picker的内容闭包里直接定义变量(workspace、applications、i)不符合SwiftUI的视图构建规则
  • 手动用i + 1设置tag的方式无效,因为i在闭包中不会随循环递增,所有选项的tag都会是1

修正后的代码

struct ContentView: View {
    @State private var selectedApp: NSRunningApplication?
    @State private var stopAppTerminate: Bool = false
    
    // 获取过滤后的运行应用(排除自身和无名称的后台进程)
    private var runningApps: [NSRunningApplication] {
        NSWorkspace.shared.runningApplications.filter {
            $0.localizedName != nil && !$0.bundleURL?.path.contains(Bundle.main.bundlePath) ?? false
        }
    }
    
    var body: some View {
        Picker(selection: $selectedApp, label: Text("等待应用终止")) {
            ForEach(runningApps, id: \.processIdentifier) { app in
                Text(app.localizedName ?? "未知应用")
                    .tag(app as NSRunningApplication?)
            }
        }
        .onChange(of: selectedApp) { newValue in
            // 替换成你的StopAppTerminateChange逻辑
            if let app = newValue {
                print("选择了应用:\(app.localizedName ?? "")")
            }
        }
    }
}

关键修正点

  • 将获取运行应用的逻辑抽成计算属性runningApps,并过滤掉无名称的进程和当前应用,避免无效选项
  • ForEach通过id: \.processIdentifier指定唯一标识(进程ID是系统分配的唯一值,比bundleIdentifier更可靠,因为有些后台进程可能没有bundleID)
  • tag直接绑定NSRunningApplication实例,确保选中状态和应用一一对应,替代原来的无效数字tag
  • 用localizedName显示应用名称,避免显示内存地址字符串
  • 将onChange移到Picker外部,符合SwiftUI的状态监听规范

内容的提问来源于stack exchange,提问作者DBR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 15:45:39