@propertyWrapper

最近看 SwiftUI 的時候使用了 @State@Binding, 在看API 的時候發(fā)現(xiàn), 他們的實現(xiàn)都是通過 @propertyWrapper 實現(xiàn)的.

@propertyWrapper

它能干什么?
可以減少重復代碼

舉個例子:

extension UserDefaults {
    public enum Key: String {
        case someInt = "someInt"
    }
    var someInt: Int {
        get {
            return integer(forKey: Key.someInt.rawValue)
        }
        set {
            set(newValue, forKey: Key.someInt.rawValue)
        }
    }
}

之前使用 UserDefaults 通常采用上面的方式, 每個 Key 都要實現(xiàn)一次 get set,
產生了大量的工作.

可以使用 @propertyWrapper 來替換這部分代碼, 實現(xiàn)如下:

@propertyWrapper
struct UserDefaultWrapper<T> {
    var key: String
    var defaultT: T!
    var wrappedValue: T! {
        get { (UserDefaults.standard.object(forKey: key) as? T) ?? defaultT }
        nonmutating set {
            if newValue == nil {
                UserDefaults.standard.removeObject(forKey: key)
            } else {
                UserDefaults.standard.set(newValue, forKey: key)
            }
        }
    }
    
    init(_ key: String, _ defaultT: T! = nil) {
        self.key = key
        self.defaultT = defaultT
    }
}
struct UserDefaultsUnit {
    @UserDefaultWrapper("test")
    static var test: String?
}

//使用
UserDefaultsUnit.test = "hahahha" // set
UserDefaultsUnit.test // get

看過上面代碼, 開始具體說一下 @propertyWrapper.
簡單的理解就是包裝屬性.
怎么包裝? 替換 setget 方法
每個 @propertyWrapper 都必須實現(xiàn)一個屬性 wrappedValue, 實現(xiàn) wrappedValueset get 就相當于替換掉原屬性的 set get.
如果你想實現(xiàn)被 @propertyWrapper 包裹的屬性 get set, 會產生錯誤 Property wrapper cannot be applied to a computed property

@propertyWrapper 的思想是, 只可以通過 wrappedValueget set 方法來訪問屬性, 所以它默認的初始化方法是下面的方法, 給wrappedValue初始值, 這個是從Swift Property Wrappers 復制過來的時候發(fā)現(xiàn)的, 但你也可以不實現(xiàn)這個方法, 通過其他的方式初始化, 比如上面 UserDefaults 的實現(xiàn).

init(wrappedValue initialValue: T) {
        self.wrappedValue = initialValue
}

Codeale 使用

/// for codable
@available(swift 5.1)
@propertyWrapper
struct UserDefaultJsonWrapper<T: Codable> {
    var key: String
    var defaultT: T!
    var wrappedValue: T {
        get {
            guard let jsonString = UserDefaults.standard.string(forKey: key) else { return defaultT }
            guard let jsonData = jsonString.data(using: .utf8) else { return defaultT }
            guard let value = try? JSONDecoder().decode(T.self, from: jsonData) else { return defaultT }
            return value
        }
        set {
            let encoder = JSONEncoder()
            guard let jsonData = try? encoder.encode(newValue) else { return }
            let jsonString = String(bytes: jsonData, encoding: .utf8)
            UserDefaults.standard.set(jsonString, forKey: key)
        }
    }
    
    init(_ key: String, _ defaultT: T! = nil) {
        self.key = key
        self.defaultT = defaultT
    }
}

@propertyWrapper 可以使用的地方有很多, 一些通用的實現(xiàn)都可以使用它來減少重復代碼.
下面是 RGB 通用的簡單實現(xiàn)

@propertyWrapper
struct RGBColorWrapper {
    private var r: CGFloat
    private var g: CGFloat
    private var b: CGFloat
    private var alpha: CGFloat
    
    var wrappedValue: UIColor { UIColor.init(red: r, green: g, blue: b, alpha: alpha) }
    
    init(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat, _ alpha: CGFloat = 1) {
        self.r = r / 255
        self.g = g / 255
        self.b = b / 255
        self.alpha = alpha
    }
}

struct Color {
    @RGBColorWrapper(255, 0, 0)
    static var redRed: UIColor
}

// 使用
view.backgroundColor = Color.redRed
Reference: Swift Property Wrappers
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市寻仗,隨后出現(xiàn)的幾起案子神年,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡垮耳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門弃酌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氨菇,“玉大人儡炼,你說我怎么就攤上這事妓湘。” “怎么了乌询?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵榜贴,是天一觀的道長。 經常有香客問我妹田,道長唬党,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任鬼佣,我火速辦了婚禮驶拱,結果婚禮上,老公的妹妹穿的比我還像新娘晶衷。我一直安慰自己蓝纲,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布晌纫。 她就那樣靜靜地躺著税迷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锹漱。 梳的紋絲不亂的頭發(fā)上箭养,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音哥牍,去河邊找鬼毕泌。 笑死,一個胖子當著我的面吹牛嗅辣,可吹牛的內容都是我干的撼泛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼辩诞,長吁一口氣:“原來是場噩夢啊……” “哼坎弯!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤抠忘,失蹤者是張志新(化名)和其女友劉穎撩炊,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體崎脉,經...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡拧咳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了囚灼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骆膝。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖灶体,靈堂內的尸體忽然破棺而出阅签,到底是詐尸還是另有隱情,我是刑警寧澤蝎抽,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布政钟,位于F島的核電站,受9級特大地震影響樟结,放射性物質發(fā)生泄漏养交。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一瓢宦、第九天 我趴在偏房一處隱蔽的房頂上張望碎连。 院中可真熱鬧,春花似錦驮履、人聲如沸鱼辙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽座每。三九已至,卻和暖如春摘悴,著一層夾襖步出監(jiān)牢的瞬間峭梳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工蹂喻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留葱椭,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓口四,卻偏偏與公主長得像孵运,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蔓彩,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內容