Swift下UserDefaults的常见使用和注意事项

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift下UserDefaults的常见使用和注意事项相关的知识,希望对你有一定的参考价值。

参考技术A

UserDefaults 适合存储轻量级的本地客户端数据,这是一种常见的数据持久化方式。(建议:如果是存储大批量的数据不要使用这个方法)

这个方法可以基于iCloud做跨设备的UserDefaults数据存储,参考 NSUbiquitousKeyValueStore

这个方法可以获得当前App存储的所有UserDefaults数据

这个通知可以在UserDefault发生改变时发出。可以考虑当这个通知发生时全局进行同步数据。 UserDefaults.didChangeNotification

ios7或者7以下,一般只会在app返回background的时候才会保存数据到disk,但是iOS8以及以上之后app都会在极其短的周期内去保存数据,除非极其频繁且大规模地进行写入的操作,一般而言都会在可接受的时间内完成这项操作。

在iOS8以及以上,读数据大约需要0.5微妙的时间,但是写入数据需要10倍左右的时间,需要将key-valu通过 NSPropertyListSerialization 转化成plist data

总而言之,iOS8以及以上的系统内不太建议使用 synchronize() 方法

enum for Keys used to store data

Save in UserDefaults where you want

Retrieve data anywhere in app

Remove Values

利用UserDefaults我们可以方便地存取一些简单的资料,然而当我们存取的资料类型是Int,Bool,Float,Double时,却会遇到一个特别的问题。因为她们回传的类型不是optional,所以不会返回nil,而是一个预设的值,比如0,false之类。可能我们存在一些需求,希望没有存储值时返回nil,那么有两种方式可以解决这个问题。

这个方法的返回值是不可选的,会有默认值

更多参考:

有些是返回可选类型的

使用register(defaults:)设定找不到key对应的value时回传的预设值,比如nil

register设定的内容是暂存的,并没有存档,所以每次App启动时都要再设定一次。(并且没有设为nil这种操作,设为nil意味着取消该项的设置,后面取值时依旧会采用默认值)

通过回传Any?的 object(forKey:) 搭配 as? 转型判断

这个方法返回值是可选的

比如:

由于回传的类型是Any?,所以找不到key number对应的value时会回传nil

参考链接: UserDefaults预设值

value(forKey:) 是KVC的语法,它并不是一个UserDefaults的直接方法。所以最好不要在 UserDefaults

Never use value(forKey:) on UserDefaults or Dictionary or any other class unless you have a clearly understood need to use key-value coding to get the desired result.

When you don\'t have such a need, use the standard access methods provided by UserDefaults object(forKey:)

再补充一点:
The value(forKey:) is not a UserDefaults-only method. It is enabled by the NSKeyValueCoding , which, According to Apple\'s Documentation.
NSKeyValueCoding is an informal protocol that objects adopt to provide indirect access to their properties. When an object is key-value coding compliant, its properties are addressable via string parameters through a concise, uniform messaging interface.

It happens that UserDefaults is NSKeyValueCoding compliant, so people have started (not necessarily in the correct way) using it for accessing UserDefaults.

简而言之,UserDefaults也是遵循了 NSKeyValueCoding 协议的,所以使用 value(forKey:) 也是可以获取到数据,但是不建议这种用法。在 UserDefaults 里面最好使用 object(forKey:) ,这是标准用法

参考链接: 在UserDefaults中object(forKey:)和value(forKey:)的区别

NSUserDefaults — A Swift Introduction
[NSUserDefaults synchronize] is Planned to be Deprecated

以上大多是一些需要注意的问题。关于Swift的常见用法,已经有很多博客在详述了,可以参考: Swift:UserDefaults协议(Swift视角下的泛字符串类型API)

swift--使用UserDefaults来进行本地数据存储

UserDefaults适合轻量级的本地客户端存储,存储一个值,新值可以覆盖旧值,可以重复存储,也可以存储一次,然后直接从UserDefaults里面读取上次存储的信息,很方便,用的时候,宏定义下,直接调用!

轻量级数据库的话,移动端一般使用SQlite数据库,也是一款轻量级的适合移动端设备的数据库,具体可以参考我以前写的关于SQlite的博客,当然了UserDefaults根本不用管这些东西,直接就想读取字符串一样,直接读取就可以了!

UserDefaults支持的数据格式也很多:有:Int,Float,Double,BOOL,Array,Dictionary,甚至 Any 类型

1. 样例展示:

 

func get_uuid() -> String {
        let userID = UserDefaults.standard.string(forKey: "HHGGLL")
        //判断UserDefaults中是否已经存在
        if userID != nil {
            return userID!
        }else{
            let uuid_ref = CFUUIDCreate(nil)
            let uuid_string_ref = CFUUIDCreateString(nil, uuid_ref)
            let uuid = uuid_string_ref! as String
            UserDefaults.standard.set(uuid, forKey: "HHGGLL")
            return uuid
        }
    }

 

输出:

 print("用户的UUID:\\(get_uuid())")

如上图!

2.其他基本数据类型和any类型的存储

 //存储练习
        let userDefault = UserDefaults.standard
        //any
        userDefault.set("hgl001", forKey: "object")
        let objectValue:Any? = userDefault.object(forKey: "object")
        print("\\(objectValue as! String)")
        //int
        userDefault.set(12345, forKey: "int")
        let intValue = userDefault.integer(forKey: "int")
        print(intValue)
        //float
        userDefault.set(3.2, forKey: "float")
        let floatValue = userDefault.float(forKey: "float")
        print(floatValue)
        //double
        userDefault.set(5.2369, forKey: "double")
        let doubleValue = userDefault.double(forKey: "double")
        print(doubleValue)
        //bool
        userDefault.set(true, forKey: "bool")
        let boolValue = userDefault.bool(forKey: "bool")
        print(boolValue)
        //url
        userDefault.set(URL(string:"http://hangge.com")!, forKey: "URL")
        let urlValue = userDefault.url(forKey: "URL")
        print(urlValue)
        //string类型
        userDefault.set("hgl is a hero!", forKey: "string")
        let stringValue = userDefault.string(forKey: "string")
        print(stringValue)
        //nsnumber类型
        var number = NSNumber(value:22)
        userDefault.set(number, forKey: "number")
        number = userDefault.object(forKey: "number") as! NSNumber
        print(number)
        //array类型
        var array:Array = ["123","223"]
        userDefault.set(array, forKey: "Array")
        array = userDefault.array(forKey: "Array") as! [String]
        print(array)
        //Dictionary类型
        var dictory = ["name":"hero11223"]
        userDefault.set(dictory, forKey: "dictory")
        dictory = userDefault.dictionary(forKey: "dictory") as! [String:String]
        print(dictory)
        //系统对象的存储与读取
        let userDeafaults = UserDefaults.standard
        //存储对象
        let label = UILabel()
        label.text = "天空飘来五个字"
        let labelData = NSKeyedArchiver.archivedData(withRootObject: label)
        //存储data对象
        userDefault.set(labelData, forKey: "labelData")
        
        //对象读取
        //获取data
        let objData = userDefault.data(forKey: "labelData")
        //还原对象
        let mylabel = NSKeyedUnarchiver.unarchiveObject(with: objData!) as? UILabel
        print(mylabel)
        //UIImage对象存储
        let image1 = UIImage(named:"1.jpeg")
        let image2 = UIImage(cgImage: (image1?.cgImage!)!, scale: (image1?.scale)!,
                             orientation: (image1?.imageOrientation)!)
        let imageData = NSKeyedArchiver.archivedData(withRootObject: image2)
        //存储Data对象
        userDefault.set(imageData, forKey: "imageData")
        
        //UIImage对象读取
        //获取Data
        let objDatas = userDefault.data(forKey: "imageData")
        //还原对象
        let myImg = NSKeyedUnarchiver.unarchiveObject(with: objDatas!)
        print("输出是\\(myImg)")

打印如下图:

 3.删除存储对象

通过removeObject()方法可以删除已保存的数据

UserDefaults.standard.removeObject(forKey: "key值")

 

以上是关于Swift下UserDefaults的常见使用和注意事项的主要内容,如果未能解决你的问题,请参考以下文章

swift--使用UserDefaults来进行本地数据存储

Swift: 用UserDefaults保存复杂对象

userdefaults 使用问题 swift 3

如何使用 userDefaults 保存打印数组(swift 3)

使用 UserDefaults() 自动登录不起作用 Swift 5

swift 使用UserDefaults保存数据