2024-03-21

平時(shí)存東西辩尊,總用到 UserDefaults秒旋,每次使用取的時(shí)候很麻煩菜枷,提供一個(gè)好的簡(jiǎn)單的方案

0.首先定義一個(gè)存儲(chǔ)讀取的模型

///當(dāng)單獨(dú)存儲(chǔ) 基本數(shù)據(jù)單元時(shí)铃芦,encode 會(huì)失敗纤壁,所以搞個(gè)中間變量 左刽,因?yàn)閱未鎯?chǔ)基本數(shù)據(jù)時(shí),

JSONDecoder().decode(LsqUserDefaultModel<T>.self, from: data)轉(zhuǎn)換失敗酌媒,所以加了個(gè)中間變量欠痴。


public struct LsqUserDefaultModel: Codable {

    var key: String? 

    var value: T? 

}

1.自定義 @LsqUserDefault

///注意 T 只能是Codable數(shù)據(jù)類型


@propertyWrapper

public struct LsqUserDefault<T: Codable> {

    let key: String

    public init(key: String)  {

        self.key = key

    }

    public var wrappedValue: T? {

          get{

              guard let data = UserDefaults.standard.object(forKey: self.key) as? Data,

                  let value =try? JSONDecoder().decode(LsqUserDefaultModel<T>self, from: data)         else {

                return nil

            }

            return value.value

        }

        set {

            if let v = newValue {

                do {

                    let model = LsqUserDefaultModel(key:key, value: v)

                    let data = try JSONEncoder().encode(model)

                    UserDefaults.standard.set(data,forKey:self.key)

                }catch{

                    print("LsqUserDefault存儲(chǔ)失敗key:\(key)")

                }

            }else{

                UserDefaults.standard.removeObject(forKey: self.key)

            }

        }

    }

}

///當(dāng)單獨(dú)存儲(chǔ) 基本數(shù)據(jù)單元時(shí)迄靠,encode 會(huì)失敗,所以搞個(gè)中間變量

public struct LsqUserDefaultModel<T: Codable>: Codable {

    var key: String?

    var value: T?

}

///注意 T 只能是Codable數(shù)據(jù)類型, 并且不能為空

@propertyWrapper

public struct LsqUserDefaultValue<T: Codable> {

    let key: String

    let defaultValue: T

    public init(key: String, _ defaultValue: T) {

        self.key = key

        self.defaultValue= defaultValue

    }

    public var wrappedValue: T  {

        get {

            guard let data = UserDefaults.standard.object(forKey: self.key) as? Data,

                  let value = try? JSONDecoder().decode(LsqUserDefaultModel.self, from: data) else {

                return self.defaultValue

            }

            return value.value ?? self.defaultValue

        }

        set {

            do {

                let model = LsqUserDefaultModel(key: key, value: newValue)

                let data = try JSONEncoder().encode(model)

                UserDefaults.standard.set(data, forKey: self.key)

            } catch {

                print("LsqUserDefaultValue存儲(chǔ)失敗key:\(key)")

            }

        }

    }

}

使用方法

1.首先我有個(gè) model

struct MyTestModel: Codable {

    var name: String?

    var value: Int?

}

2.@LsqUserDefault(key: "你的名字喇辽,要唯一") 不能放在最頂層

struct App {

    *沒有默認(rèn)值的多個(gè)存儲(chǔ)

     @LsqUserDefault(key: "AppConfigModelList")

      static var testList: [MyTestModel]?


    *沒有默認(rèn)值的單個(gè)存儲(chǔ)

     @LsqUserDefault(key: "AppConfigModelOne")

    static var test: MyTestModel?


    *帶有默認(rèn)值的存儲(chǔ)

     @LsqUserDefaultValue(key: "AppConfigModelNotNil", MyTestModel())

    static var testNotNil: MyTestModel


    *帶有默認(rèn)值的存儲(chǔ) 基本數(shù)據(jù)類型

    @LsqUserDefaultValue(key: "KisLoginKey", false)

    static var isLogin: Bool

}

3使用------>>>>

class XxxxxCtr: UIViewController {

override func viewDidLoad() {

    super.viewDidLoad()



///讀取

let isLogin = App.isLogin

///存儲(chǔ)

 App.isLogin = true    

///讀取

let test = App.test

///存儲(chǔ)

 App.test = nil 

App.test = MyTestModel(.....)

}

}
還有就是服務(wù)器返回的數(shù)據(jù)類型不確定時(shí)掌挚,我封裝了一個(gè)數(shù)據(jù)類型轉(zhuǎn)換的

public protocol LsqCodable: Codable {

associatedtype T: Codable

var wrappedValue: T? { get set }

}

///注意 String、 Int 和 Double 都轉(zhuǎn)換成String, 返回?cái)?shù)據(jù)類型不明確時(shí)使用

@propertyWrapper

public struct LsqStringable: LsqCodable {

public var wrappedValue:String?

public init(wrappedValue:String? =nil) {

    self.wrappedValue= wrappedValue

}

public init(from decoder:Decoder) throws {

    let container = try decoder.singleValueContainer()

    if container.decodeNil() {

       return

    }

    if let value = try? container.decode(String.self) {

        wrappedValue= value

    } else if let value = try? container.decode(Int.self) {

        wrappedValue="\(value)"

    } else { 

        do {

            let value = try container.decode(Double.self)

            wrappedValue= value.stringValue

        } catch {

            print("<====【解析異称凶桑】===>我不是String吠式、Int、也不是Double==>\(error)")

        }

    }

}

}

///注意 Int抽米、String 都轉(zhuǎn)換成Int, 返回?cái)?shù)據(jù)類型不明確時(shí)使用

@propertyWrapper

public struct LsqIntable: LsqCodable {

public var wrappedValue:Int?

public init(wrappedValue:Int? =nil) {

    self.wrappedValue= wrappedValue

}

public init(from decoder:Decoder) throws {

    let container = try decoder.singleValueContainer()

    if container.decodeNil() {

       return

    }

    if let value = try? container.decode(Int.self) {

        wrappedValue= value

    }else{

        do{

            let value = try container.decode(String.self)

            if let intValue =Int(value) {

                wrappedValue= intValue

            }else{

                print("<====【解析異程卣迹】===>LsqIntable不能將String轉(zhuǎn)換為Int***\(container.codingPath)")

            }

        }catch{

            print("<====【解析異常】===>我不是Int云茸、也不是String==>\(error)")

        }

    }

}

}

///注意 Bool摩钙、String 都轉(zhuǎn)換成Bool, 返回?cái)?shù)據(jù)類型不明確時(shí)使用

@propertyWrapper

public struct LsqBoolable: LsqCodable {

public var wrappedValue:Bool?

public init(wrappedValue:Bool? =nil) {

    self.wrappedValue= wrappedValue

}

public init(from decoder:Decoder) throws {

    let container =try decoder.singleValueContainer()

    if container.decodeNil() {

       return

    }

    if let value = try? container.decode(Bool.self) {

        wrappedValue= value

    }else{

        do{

            let value = try container.decode(String.self)

            if let boolValue =Bool(value) {

                wrappedValue= boolValue

            }else{

                print("<====【解析異常】===>LsqBoolable不能將String轉(zhuǎn)換為Bool***\(container.codingPath)")

            }

        }catch{

            print("<====【解析異巢楸纾】===>我不是Bool胖笛、也不是String==>\(error)")

        }

    }

}

}

///注意 Double、String 都轉(zhuǎn)換成Double, 返回?cái)?shù)據(jù)類型不明確時(shí)使用

@propertyWrapper

public struct LsqDoubleable: LsqCodable {

public var wrappedValue:Double?

public init(wrappedValue:Double? =nil) {

    self.wrappedValue= wrappedValue

}

public init(from decoder:Decoder) throws {

    let container =try decoder.singleValueContainer()

    if container.decodeNil() {

       return

    }

    if let value = try? container.decode(Double.self) {

        wrappedValue= value

    } else {

        do {

            let value =try container.decode(String.self)

            if let doubleValue =Double(value) {

                wrappedValue= doubleValue

            } else {

                print("<====【解析異骋说海】===>LsqDoubleable不能將String轉(zhuǎn)換為Double***\(container.codingPath)")

            }

        } catch {

            print("<====【解析異吵び唬】===>我不是Double、也不是String==>\(error)")

        }

    }

}

}

extension KeyedEncodingContainer {

mutating func encode(_ value: some LsqCodable, forKey key: Self.Key) throws {

    try encodeIfPresent(value.wrappedValue, forKey: key)

}

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末萍倡,一起剝皮案震驚了整個(gè)濱河市身弊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌列敲,老刑警劉巖阱佛,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異戴而,居然都是意外死亡凑术,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門所意,熙熙樓的掌柜王于貴愁眉苦臉地迎上來淮逊,“玉大人,你說我怎么就攤上這事扶踊⌒古簦” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵秧耗,是天一觀的道長(zhǎng)备籽。 經(jīng)常有香客問我,道長(zhǎng)分井,這世上最難降的妖魔是什么车猬? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任霉猛,我火速辦了婚禮,結(jié)果婚禮上诈唬,老公的妹妹穿的比我還像新娘。我一直安慰自己缩麸,他們只是感情好铸磅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著杭朱,像睡著了一般阅仔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上弧械,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天八酒,我揣著相機(jī)與錄音,去河邊找鬼刃唐。 笑死羞迷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的画饥。 我是一名探鬼主播衔瓮,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼抖甘!你這毒婦竟也來了热鞍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤衔彻,失蹤者是張志新(化名)和其女友劉穎薇宠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體艰额,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡澄港,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了柄沮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慢睡。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖铡溪,靈堂內(nèi)的尸體忽然破棺而出漂辐,到底是詐尸還是另有隱情,我是刑警寧澤棕硫,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布髓涯,位于F島的核電站,受9級(jí)特大地震影響哈扮,放射性物質(zhì)發(fā)生泄漏纬纪。R本人自食惡果不足惜蚓再,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望包各。 院中可真熱鬧摘仅,春花似錦、人聲如沸问畅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽护姆。三九已至矾端,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卵皂,已是汗流浹背秩铆。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留灯变,地道東北人殴玛。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像添祸,于是被迫代替她去往敵國(guó)和親族阅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容