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

SwiftUI中调用耗时函数前如何切换为Apple忙碌光标?

SwiftUI耗时操作时显示系统忙碌光标解决方案

你的代码存在两个关键问题:一是没使用正确的系统忙碌光标,二是耗时操作阻塞主线程导致光标状态无法正常更新。以下是修正方案:

核心修改点

  • 系统忙碌光标对应NSCursor.busy,而非closedHand
  • 必须将文件导入这类耗时操作放到后台线程执行,避免卡死UI

修正后的完整代码

Button(action: {
    // 主线程切换为忙碌光标
    NSCursor.busy.push()
    
    // 后台队列执行耗时操作(userInitiated优先级匹配用户触发的任务)
    DispatchQueue.global(qos: .userInitiated).async {
        // 执行耗时的文件处理逻辑
        let fetchedItems = getImageList(folder)
        importImages(fetchedItems)
        
        // 回到主线程更新UI并恢复光标
        DispatchQueue.main.async {
            self.images = fetchedItems
            NSCursor.pop()
        }
    }
}) {
    Text("Import Images")
}

进阶优化:确保光标必恢复

为了避免操作出错时光标一直处于忙碌状态,可以用defer语句保证pop()一定会执行:

Button(action: {
    NSCursor.busy.push()
    
    DispatchQueue.global(qos: .userInitiated).async {
        // 无论成功失败,最终都会执行这里的代码
        defer {
            DispatchQueue.main.async {
                NSCursor.pop()
            }
        }
        
        do {
            let fetchedItems = getImageList(folder)
            importImages(fetchedItems)
            DispatchQueue.main.async {
                self.images = fetchedItems
            }
        } catch {
            // 这里添加错误处理逻辑,比如弹窗提示用户导入失败
            DispatchQueue.main.async {
                // 示例:显示错误提示
                // self.errorMessage = "导入失败:\(error.localizedDescription)"
            }
        }
    }
}) {
    Text("Import Images")
}

关键说明

  • NSCursor.busy是macOS系统默认的等待光标(彩色旋转沙滩球样式)
  • 耗时操作必须脱离主线程:如果在主线程执行,UI会被完全冻结,光标切换的指令根本无法被系统处理
  • 所有UI相关操作(包括光标状态切换、images变量更新)必须回到主线程执行,这是SwiftUI的线程安全要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 12:02:45