Created
February 24, 2017 07:18
-
-
Save edwardaux/60c106ab6876c3c3c16216ae8d714108 to your computer and use it in GitHub Desktop.
A simple expression watcher for Swift apps
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Sometimes you want to watch a particular expression over time. Continually dumping | |
// the value in a loop can be painful because of the sheer volume of values. This snippet | |
// loops on a background thread checking the result of the passed expression - if the | |
// value changes (and only then) does it output the new value. Note that this is NOT meant | |
// as a replacement for a KVO-observable property... it is better suited to expressions | |
// that do not post KVO events. | |
// | |
// Usage: watchExpression(every: 0.1) { someCodeThatReturnsAValue() } | |
// | |
// You can control how often the value will be checked using the every parameter (the example | |
// above checks every 100ms). The return value can be any object that conforms to the | |
// Equatable protocol. | |
// | |
// Note that this is NOT meant to be left in production code. It is purely meant to be | |
// a debugging tool. | |
var timer: DispatchSourceTimer? | |
func watchExpression<T: Equatable>(every: TimeInterval, expression: @escaping () -> T?) { | |
let formatter = DateFormatter() | |
formatter.dateFormat = "HH:mm:ss.SSS" | |
formatter.timeZone = TimeZone.current | |
func dump(value: T?) { | |
let output: Any = value ?? "nil" | |
let time = formatter.string(from: Date()) | |
print(">>> \(time) \(output)") | |
} | |
var previousValue = expression() | |
dump(value: previousValue) | |
let queue = DispatchQueue(label: "expression.watcher", attributes: .concurrent) | |
timer?.cancel() | |
timer = DispatchSource.makeTimerSource(flags: [], queue: queue) | |
timer?.scheduleRepeating(deadline: .now(), interval: every) | |
timer?.setEventHandler { | |
let currentValue = expression() | |
if currentValue != previousValue { | |
dump(value: currentValue) | |
previousValue = currentValue | |
} | |
} | |
timer?.resume() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment