Swift5 归档解档,本地数据持久化存储之UserDefaults

一、对象的归档与解档需要遵循NSCoding和NSSecureCoding协议

其中NSSecureCoding协议更加安全

归档:把要保存的内容转为Data后保存到指定位置

解档:把指定位置的Data转为需要的对象

1.NSDictionary也可以直接进行归档和解档

2.归档的对象包括这个对象中的属性,它们所属类的都必须要遵守NSCoding协议才能归档和解档

2.自定义类的归档和解档

如果自定义的类对象要进行归档那么这个对象的属性所属的类也必须要遵守归档协议NSCoding

归档时不一定要直接归档到文件,还可以先将他们归档成NSData,然后将NSData进行存储,用的时候就用这个NSData解档

必须实现三个协议方法如下:   

static var supportsSecureCoding: Bool {
        return true
}
func encode(with coder: NSCoder) {

}
required init?(coder: NSCoder) {

}

二、归档协议方法调用如下:

    fileprivate func handlePropertyEnCoder(_ acoder: NSCoder) {

        let outCount = UnsafeMutablePointer<UInt32>.allocate(capacity: 0)

        let propertys = class_copyPropertyList(self.classForCoder, outCount)

        let count = Int(outCount[0])


        for i in 0..<count {

            if let property = propertys?[i] {

                ///获取属性名

                guard let proName = String(utf8String: property_getName(property)) else {

                    continue

                }

                

                let propertyValue = self.value(forKey: proName)

                if propertyValue != nil  {

                    ///获取属性值

                    guard let Attributes = property_getAttributes(property) else {

                        continue

                    }

                    ///属性值转string

                    guard let AttributeString: String = String(utf8String: Attributes) else {

                        continue

                    }

                    

                    let b:CharacterSet = NSCharacterSet(charactersIn: ",") as CharacterSet

                    let AttributeArray = AttributeString.components(separatedBy: b)

                    

                    if AttributeArray.contains("R") {

                        ///只读属性不做处理

                    }else {

                        // TODO: 注意

                        acoder.encode(propertyValue, forKey: proName)

                    }

                }

            }

        }

        ///释放内存

//        free(propertys)

    }

三、解档协议方法调用如下:

fileprivate func handlePropertyDeCoder(_ acoder: NSCoder) {

        var outCount: UInt32 = 0

        let propertys = class_copyPropertyList(self.classForCoder, &outCount)

        let count = Int(outCount)

        

        for i in 0..<count {

            if let property = propertys?[i] {

                

                guard let propertyName = String(utf8String: property_getName(property)) else {

                    continue

                }

                let propertyValue = acoder.decodeObject(forKey: propertyName)

                if propertyValue != nil {

                    

                    ///获取属性值

                    guard let attributes = property_getAttributes(property) else {

                        continue

                    }

                    

                    guard let attributeString = String(utf8String: attributes) else {

                        continue

                    }

                    

                    let b: CharacterSet = CharacterSet(charactersIn: ",") as CharacterSet

                    let attributeArray = attributeString.components(separatedBy: b)

                    if attributeArray.contains("R") {

                        //只读属性暂不读取

                    }else {

                        self.setValue(propertyValue, forKey: propertyName)

                    }

                }

            }

        }

    }

四、数据持久之UserDefaults

NSUserDefaults适合存储轻量级的本地数据。比如要保存一个登陆界面的数据,用户名、密码之类

NSUserDefaults存储的数据在应用程序内置的一个plist文件里

NSUserDefaults支持的数据格式有:NSNumber(Integer、Float、Double),NSString,NSDate,NSArray,NSDictionary,BOOL类型。

存储时,除NSNumber类型使用对应的类型意外,其他的都是使用setObject:forKey:

1、存储信息

/// 数据持久化到本地   

func pr_saveToLocalData() {

        if #available(iOS 11.0, *) {

            ///对象转为数据后写到指定位置

            let infoData: Data? = try? NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding:false)

            if infoData != nil {

                PRUserDefaultsSaveData(infoData, pr_getClassName())

           }

        } else {

            // Fallback on earlier versions

            let infoData: Data? = NSKeyedArchiver.archivedData(withRootObject: self)

            if infoData != nil {

                PRUserDefaultsSaveData(infoData, String(utf8String: object_getClassName(self)))

            }

        }

    }

2、获取信息

///加载本地数据

   static func pr_loadLocalData() -> Any? {

      let infoData: Data? = PRUserDefaultsGetObject(pr_getClassName()) as? Data

      /// 把Data转为对象

      if infoData != nil {

           if #available(iOS 11.0, *) {

               let info = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(infoData!) as? PRUserDataInfoProperty

              return info

           } else {

               // Fallback on earlier versions

               let info = NSKeyedUnarchiver.unarchiveObject(with: infoData!)

              return info

           }

       }

       return nil

    }

3、清除信息

///清除缓存数据

    func pr_clearLocalData() {
        PRUserDefaultsRemoveObject(pr_getClassName())
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值