平時(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)
}
}