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
相关产品推荐
相关产品推荐

