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

macOS 14下NSCursor.push()/.set()设置自定义光标被频繁重置问题

macOS 14自定义光标频繁重置问题排查

在macOS 14中出现了macOS 13未存在的异常:原本可以在应用特定视图区域设置自定义鼠标光标,现在光标会频繁重置为标准箭头光标。

用以下代码可复现该问题:鼠标移入红色矩形时光标应变为手型,移出时恢复箭头,但移至矩形右侧时光标会快速重置为箭头,左侧则常保持手型;即使取消注释cursor?.set()行,光标也会在箭头和手型间闪烁。请问这是已知Bug还是我的实现有误?

class ViewController: NSViewController {
    
    var cursor: NSCursor?
    let subframe = CGRect(x: 100, y: 100, width: 300, height: 100)

    override func loadView() {
        let subview = NSView(frame: subframe)
        subview.wantsLayer = true
        subview.layer!.backgroundColor = NSColor.red.cgColor
        view = NSView(frame: CGRect(x: 0, y: 0, width: 500, height: 300))
        view.addSubview(subview)
        view.addTrackingArea(NSTrackingArea(rect: .zero, options: [.activeInKeyWindow, .inVisibleRect, .cursorUpdate, .mouseMoved], owner: self))
    }
    
    override func mouseMoved(with event: NSEvent) {
        if subframe.contains(view.convert(event.locationInWindow, from: nil)) {
            if cursor == nil {
                cursor = .openHand
                cursor!.push()
                print("set cursor")
            }
        } else if let cursor = cursor {
            cursor.pop()
            self.cursor = nil
            print("unset cursor")
        }
//        cursor?.set()
    }
    
}

问题分析与解决方案

你的实现存在两处核心问题,同时macOS 14的光标管理逻辑也有调整,共同导致了异常:

  1. 错误依赖mouseMoved事件管理光标
    mouseMoved的触发频率和系统光标更新机制不同步,macOS 14会更主动地校验光标状态,当系统认为光标状态不符合视图层级预期时,会强制重置为默认箭头。正确的做法是重写视图的cursorUpdate(with:)方法,让系统自动处理光标切换。

  2. 手动管理光标栈易出现状态不一致
    用push()和pop()维护光标栈时,若系统在后台自动调整栈状态(比如某些系统事件触发),你的代码维护的cursor变量会和实际栈状态脱节,导致光标闪烁或重置。

修正后的代码

直接在目标子视图中重写光标更新方法,让系统原生处理光标逻辑:

class ViewController: NSViewController {
    
    let subframe = CGRect(x: 100, y: 100, width: 300, height: 100)

    override func loadView() {
        let subview = CustomCursorView(frame: subframe)
        subview.wantsLayer = true
        subview.layer!.backgroundColor = NSColor.red.cgColor
        view = NSView(frame: CGRect(x: 0, y: 0, width: 500, height: 300))
        view.addSubview(subview)
    }
}

class CustomCursorView: NSView {
    override func cursorUpdate(with event: NSEvent) {
        NSCursor.openHand.set()
    }
}

关于是否是已知Bug

目前苹果开发者社区有不少类似反馈,macOS 14在手动通过光标栈管理自定义光标时,确实存在异常重置的情况。因此优先推荐使用系统原生的视图级光标处理方案,避免手动维护光标栈。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 01:12:49