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

如何避免macOS窗口调整大小时onHover触发错误信号?

解决SwiftUI窗口缩放/全屏时onHover误触发问题

当窗口缩放或切换全屏模式后,onHover会短暂触发false再变回true,这是视图重绘过程中临时丢失hover状态导致的。要实现可靠的光标进入/退出检测,可通过**防抖(Debounce)**过滤短时间内的状态波动。

方案一:Combine防抖实现

利用Combine的debounce操作符,仅在状态稳定一段时间后处理最终hover状态:

import SwiftUI
import Combine

struct ContentView: View {
    @State private var isHoveringState = false
    private let hoverDebounce = PassthroughSubject<Bool, Never>()
    private var cancellables = Set<AnyCancellable>()
    
    init() {
        hoverDebounce
            .debounce(for: .milliseconds(100), scheduler: DispatchQueue.main)
            .sink(receiveValue: { newValue in
                isHoveringState = newValue
                print(newValue) // 在这里处理最终的hover逻辑
            })
            .store(in: &cancellables)
    }
    
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .onHover { isHovering in
            hoverDebounce.send(isHovering)
        }
    }
}

#Preview {
    ContentView()
}

方案二:Timer防抖实现

若不想引入Combine,可手动用Timer实现防抖逻辑:

struct ContentView: View {
    @State private var isHoveringState = false
    private var hoverTimer: Timer?
    
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .onHover { isHovering in
            // 每次状态变化时取消之前的定时器
            hoverTimer?.invalidate()
            // 100毫秒后确认最终状态
            hoverTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false) { _ in
                isHoveringState = isHovering
                print(isHoveringState) // 处理最终hover逻辑
            }
        }
    }
}

#Preview {
    ContentView()
}

说明

  • 防抖时间设为100毫秒,既可以过滤窗口调整带来的临时状态波动,又不会影响正常hover交互,可根据需求自行调整时间值。
  • 两种方案都能确保仅当光标状态稳定后,才触发业务逻辑,避免窗口调整时的误触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 18:35:02