在 Swift 5.1 之前, 每當我們看到 @_SOME_
時, 都會去 Swift.org 查找 grammar_attribute-name, 像是 @IBOutlet
或是 @escaping
.
而在 Swift 5.1 之後, 我們有了 Property Wrappers
Swift Evolution: SE-0258, 而這個將 Publisher
封裝起來, 透過 Compiler 轉化 原始碼, 讓程式碼更好處理與閱讀.
請參考下面原始碼:
struct UserDefulted<Value> {
private let defaults = UserDefaults.standard
var defaultValue:Value // 1
private let key:String // 2
var value:Value {
get { // 3
return defaults.object(forKey: key) as? Value ?? defaultValue
}
set {
defaults.set(newValue, forKey: key)
}
}
}
在這個範例中, 我們在取用值得時候並沒有想象的方便
var myValue = UserDefaulted("SOME", defaultValue: 1)
myValue.value = 1
var b:Int = myValue.value
這時, 可以使用 Property Wrappers
來強硬封裝抽象嵌套:
@propertyWrapper
struct UserDefault<T> {
let key: String
let defaultValue: T
init(_ key: String, defaultValue: T) {
self.key = key
self.defaultValue = defaultValue
}
var wrappedValue: T {
get {
return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
}
set {
UserDefaults.standard.set(newValue, forKey: key)
}
}
}
調用方式:
@UserDefault("Some", defaultValue: 1) var udAsset:Int
udAsset = 2
let c = udAsset
如此一來,就可以在調用時減少多餘的訊息。
@Published
請看以下原始碼
@propertyWrapper struct Published<Value>
class MyFoo { // 1
@Published var bar: String // 2
init(bar: String) {
self.bar = bar
}
}
let foo = MyFoo(bar: "bar")
let barSink = foo.$bar
.sink() {
print("bar value: \($0)")
}
bar
is String
, $bar
is Publisher有沒有很像CurrentValueSubject
呢?
參考來源:
Property wrappers to remove boilerplate code in Swift https://www.avanderlee.com/swift/property-wrappers/