平时存东西,总用到 UserDefaults,每次使用取的时候很麻烦,提供一个好的简单的方案
0.首先定义一个存储读取的模型
///当单独存储 基本数据单元时,encode 会失败,所以搞个中间变量 ,因为单存储基本数据时,
JSONDecoder().decode(LsqUserDefaultModel<T>.self, from: data)转换失败,所以加了个中间变量。
```
public struct LsqUserDefaultModel: Codable {
var key: String?
var value: T?
}
```
1.自定义 @LsqUserDefault
///注意 T 只能是Codable数据类型
```
@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{
ifletv = newValue {
do{
letmodel =LsqUserDefaultModel(key:key, value: v)
letdata =tryJSONEncoder().encode(model)
UserDefaults.standard.set(data,forKey:self.key)
}catch{
print("LsqUserDefault存储失败key:\(key)")
}
}else{
UserDefaults.standard.removeObject(forKey: self.key)
}
}
}
}
```
///当单独存储 基本数据单元时,encode 会失败,所以搞个中间变量
public struct LsqUserDefaultModel<T: Codable>: Codable {
var key: String?
var value: T?
}
///注意 T 只能是Codable数据类型, 并且不能为空
@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存储失败key:\(key)")
}
}
}
}
***使用方法***
1.首先我有个 model
struct MyTestModel: Codable {
varname:String?
varvalue:Int?
}
2.@LsqUserDefault(key: "你的名字,要唯一") 不能放在最顶层
struct App {
*没有默认值的多个存储
@LsqUserDefault(key: "AppConfigModelList")
static var testList: [MyTestModel]?
*没有默认值的单个存储
@LsqUserDefault(key: "AppConfigModelOne")
static var test: MyTestModel?
*带有默认值的存储
@LsqUserDefaultValue(key: "AppConfigModelNotNil", MyTestModel())
static var testNotNil: MyTestModel
*带有默认值的存储 基本数据类型
@LsqUserDefaultValue(key: "KisLoginKey", false)
static var isLogin:Bool
}
3使用------>>>>
class XxxxxCtr: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
///读取
let isLogin = App.isLogin
///存储
App.isLogin = true
///读取
let test = App.test
///存储
App.test = nil
App.test = MyTestModel(.....)
}
}
还有就是服务器返回的数据类型不确定时,我封装了一个数据类型转换的
public protocol LsqCodable: Codable {
associatedtype T: Codable
var wrappedValue: T? { get set }
}
///注意 String、 Int 和 Double 都转换成String, 返回数据类型不明确时使用
@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 都转换成Int, 返回数据类型不明确时使用
@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转换为Int***\(container.codingPath)")
}
}catch{
print("<====【解析异常】===>我不是Int、也不是String==>\(error)")
}
}
}
}
///注意 Bool、String 都转换成Bool, 返回数据类型不明确时使用
@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转换为Bool***\(container.codingPath)")
}
}catch{
print("<====【解析异常】===>我不是Bool、也不是String==>\(error)")
}
}
}
}
///注意 Double、String 都转换成Double, 返回数据类型不明确时使用
@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转换为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)
}
}