Swift RunLoop:收到currentMode更改的通知



当RunLoop类的currentMode属性发生更改时,我有兴趣得到通知,更具体地说,当模式进入.tracking状态时,我感兴趣得到事件。

我尝试了两种不同的方法:

这个根本不起作用,它可能有什么问题?:

import Foundation
public final class RunLoopTracker {
private let runLoop: RunLoop
private var observation: NSKeyValueObservation?
public init(runLoop: RunLoop) {
self.runLoop = runLoop
}

public func attach() {
observation = runLoop.observe(.currentMode) { runLoop, change in
print(change)
}
}
}

这个有效,但只发射一次。我想在每次RunLoop进入特定模式时执行块:

import Foundation
public final class RunLoopTracker2 {
private let runLoop: RunLoop
private var observation: NSKeyValueObservation?
public init(runLoop: RunLoop) {
self.runLoop = runLoop
}

public func attach() {
runLoop.perform(inModes: [.tracking]) {
print("Entering the tracking mode, send notification")
}
}
}

这两个问题的解决方案是什么,或者用不同的方法来跟踪RunLoop.currentMode的变化?

我完成了以下解决方案:

import Foundation
import Combine
final class RunLoopModeTracker: ObservableObject {
@Published var isTracking = false
private let runLoop: RunLoop
private var taskSet = false
public init(runLoop: RunLoop = .main) {
self.runLoop = runLoop
submitTaskForTrackingMode()
}

private func submitTaskForTrackingMode() {
if !taskSet {
runLoop.perform(inModes: [.tracking]) { [weak self] in
self?.notify()
}
taskSet = true
}
}
private func notify() {
isTracking = true
taskSet = false
submitTaskForDefaultMode()
}

private func submitTaskForDefaultMode() {
if !taskSet {
runLoop.perform(inModes: [.default]) { [weak self] in
guard let self = self else {return}
self.isTracking = false
self.submitTaskForTrackingMode()
}
}
}
}

然后在呼叫站点,我就这样使用它:

@StateObject private var runLoopTracker = RunLoopModeTracker()
/// ...
.onChange(of: runLoopTracker.isTracking) { isTracking                 
/// isTracking value has changed to true
}

本质上,这个想法是为defaulttracking模式添加任务,一旦运行循环进入其中任何一个模式,就相应地更新状态。

相关内容

  • 没有找到相关文章

最新更新