Created
July 18, 2021 13:22
-
-
Save woodycatliu/82adb528e293d6af2aa4cfbe6f345b4e 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