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

如何在SwiftUI的ContentView结构体中运行指定Swift代码?

解决SwiftUI中嵌入系统窗口信息获取代码的问题

问题分析

你遇到的问题主要源于几点:

  1. API依赖限制:CGWindowList系列接口是macOS专属的,若你创建的是iOS SwiftUI项目,导入Cocoa会报错,且无法调用这些系统窗口接口。
  2. 代码位置错误:直接把获取窗口的代码放在ContentView结构体全局区域或body计算属性里,不符合SwiftUI规则——body仅用于构建视图,不能执行调用系统API这类有副作用的代码。
  3. 强制解包风险:原代码用as!强制类型转换,一旦某个窗口信息缺失对应字段,会直接导致程序崩溃。
  4. 结果无法可视化:print仅输出到控制台,不会在UI界面展示,需要把数据绑定到视图状态中。

解决方案

以下是适配macOS SwiftUI项目的完整代码,解决了上述所有问题:

import SwiftUI
import Cocoa // 必须导入,依赖macOS的CoreGraphics窗口API

struct ContentView: View {
    @State private var visibleWindowsInfo = "" // 存储窗口信息,用于UI展示
    
    var body: some View {
        VStack(spacing: 20) {
            // 按钮手动触发获取操作
            Button("获取可见窗口信息") {
                fetchVisibleWindows()
            }
            .buttonStyle(.borderedProminent)
            
            // 滚动视图展示长文本
            ScrollView {
                Text(visibleWindowsInfo)
                    .padding()
                    .font(.system(.body, design: .monospaced)) // 等宽字体提升可读性
            }
        }
        .frame(width: 600, height: 400)
        .onAppear {
            // 视图加载完成后自动获取一次窗口信息
            fetchVisibleWindows()
        }
    }
    
    // 封装获取窗口信息的私有方法
    private func fetchVisibleWindows() {
        let options = CGWindowListOption(arrayLiteral: .excludeDesktopElements, .optionOnScreenOnly)
        // 用可选绑定替代强制解包,避免崩溃
        guard let windowsListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0)) as? [[String: Any]] else {
            visibleWindowsInfo = "无法获取系统窗口信息"
            return
        }
        
        // 过滤层级为0的可见窗口,安全处理字段提取
        let visibleWindows = windowsListInfo.filter { windowInfo in
            guard let layer = windowInfo["kCGWindowLayer"] as? Int else {
                return false
            }
            return layer == 0
        }
        
        // 将原始字典数据转为可读字符串
        if visibleWindows.isEmpty {
            visibleWindowsInfo = "未检测到可见窗口"
        } else {
            let formattedInfo = visibleWindows.map { window in
                let windowID = window["kCGWindowNumber"] as? Int ?? 0
                let windowName = window["kCGWindowName"] as? String ?? "无窗口名称"
                let ownerApp = window["kCGWindowOwnerName"] as? String ?? "未知应用"
                return "窗口ID:\(windowID)\n窗口名称:\(windowName)\n所属应用:\(ownerApp)"
            }.joined(separator: "\n\n")
            
            visibleWindowsInfo = formattedInfo
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

关键说明

  • 项目要求:必须创建macOS SwiftUI项目,iOS项目无法使用CGWindowList相关接口。
  • 状态绑定:用@State修饰visibleWindowsInfo,数据更新时SwiftUI会自动刷新UI。
  • 安全处理:全程用guard let处理可选类型,避免强制解包引发的崩溃。
  • 可视化展示:把原始字典数组转为易读的字符串,通过ScrollView适配长文本内容。
  • 触发逻辑:既支持按钮手动触发,也会在视图加载完成时自动执行一次获取操作。

内容的提问来源于stack exchange,提问作者Ravindu Tharanga Perera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 16:15:41