Created
July 18, 2021 13:22
-
-
Save woodycatliu/bfc72257c34eb50ab1f86e96254f08f1 to your computer and use it in GitHub Desktop.
這是從 https://github.com/ailabstw/social-distancing-ios 搬運出來的 Observed 屬性包裝器
This file contains 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
import Foundation | |
@propertyWrapper | |
public class Observed<T> { | |
private var _value: T { | |
didSet { | |
execute() | |
} | |
} | |
private var _closure: ((T) -> Void)? { | |
didSet { | |
execute() | |
} | |
} | |
private var _queue: DispatchQueue? = nil | |
public var wrappedValue: T { | |
get { | |
_value | |
} | |
set { | |
_value = newValue | |
} | |
} | |
public var projectedValue: Observed<T> { | |
self | |
} | |
public init(wrappedValue: T, queue: DispatchQueue? = nil) { | |
self._value = wrappedValue | |
self._queue = queue | |
} | |
public func observe(using block: @escaping (T) -> Void) { | |
_closure = block | |
} | |
/** | |
callAsFunction 為 Swift 5.0 新的語法糖 | |
請參考 [AppCoda](https://www.appcoda.com.tw/swift-5-2/) | |
*/ | |
public func callAsFunction(using block: @escaping (T) -> Void) { | |
observe(using: block) | |
} | |
public func cancel() { | |
_closure = nil | |
} | |
private func execute() { | |
guard let closure = _closure else { | |
return | |
} | |
let value = _value | |
// If target queue is .main and currently running on main thread, no need to execute async. | |
// | Queue | Thread | Operation | | |
// | -------- | -------- | --------- | | |
// | nil | main | sync | | |
// | nil | not main | sync | | |
// | main | main | sync | | |
// | main | not main | async | | |
// | not main | main | async | | |
// | not main | not main | async | | |
if let queue = _queue, (queue != DispatchQueue.main || Thread.isMainThread == false) { | |
queue.async { | |
closure(value) | |
} | |
} else { | |
closure(value) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment