如何在Swift应用程序中保存本地数据?

时间:2015-02-20 11:46:24

标签: ios swift nsuserdefaults

我目前正在开发一个在Swift中开发的iOS应用程序,我需要在设备上存储一些用户创建的内容,但我似乎无法找到一种简单快捷的方式来存储/接收用户内容。设备。

有人可以解释如何存储和访问本地存储吗?

我们的想法是在用户执行操作时存储数据,并在应用启动时接收数据。

10 个答案:

答案 0 :(得分:175)

如果您只是存储两个字符串,那么最简单的解决方案是NSUserDefaults,在Swift 3中,此类已重命名为UserDefaults

最好将密钥存储在全球某个位置,以便您可以在代码中的其他位置重复使用它们。

struct defaultsKeys {
    static let keyOne = "firstStringKey"
    static let keyTwo = "secondStringKey"
}

Swift 3.0,4.0& 5.0

// Setting

let defaults = UserDefaults.standard
defaults.set("Some String Value", forKey: defaultsKeys.keyOne)
defaults.set("Another String Value", forKey: defaultsKeys.keyTwo)

// Getting

let defaults = UserDefaults.standard
if let stringOne = defaults.string(forKey: defaultsKeys.keyOne) {
    print(stringOne) // Some String Value
}
if let stringTwo = defaults.string(forKey: defaultsKeys.keyTwo) {
    print(stringTwo) // Another String Value
}

Swift 2.0

// Setting

let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("Some String Value", forKey: defaultsKeys.keyOne)
defaults.setObject("Another String Value", forKey: defaultsKeys.keyTwo)

// Getting

let defaults = NSUserDefaults.standardUserDefaults()
if let stringOne = defaults.stringForKey(defaultsKeys.keyOne) {
    print(stringOne) // Some String Value
}
if let stringTwo = defaults.stringForKey(defaultsKeys.keyTwo) {
    print(stringTwo) // Another String Value
}

对于比次要配置,标志或基本字符串更严重的任何东西,你应该使用某种持久性存储 - 目前流行的选项是Realm但你也可以使用SQLite或者苹果非常拥有CoreData

答案 1 :(得分:48)

他们说使用NSUserDefaults

当我第一次实施长期(在应用程序关闭后)数据存储时,我在网上阅读的所有内容都指向了NSUserDefaults。但是,我想存储一本字典,虽然可能,但它确实是一种痛苦。我花了好几个小时试图让类型错误消失。

NSUserDefaults功能也有限

进一步阅读揭示了NSUserDefaults的读/写操作如何真正迫使应用程序一次性读取/写入所有内容,所以它不是有效的。然后我了解到检索数组并不是直接的。我意识到如果你要存储多个字符串或布尔值,NSUserDefaults确实不是理想的。

它也不具备可扩展性。如果您正在学习如何编码,请学习可扩展的方法。仅使用NSUserDefaults存储与首选项相关的简单字符串或布尔值。使用Core Data存储数组和其他数据,并不像他们说的那么难。从小做起。

更新:此外,如果您添加Apple Watch支持,还有另一个潜在的考虑因素。您应用的NSUserDefaults现在会自动发送到Watch Extension。

使用核心数据

所以我忽略了关于核心数据的警告是一个更难解决的问题,并开始阅读。在三个小时内我就开始工作了。我将我的表数组保存在Core Data中,并在打开应用程序时重新加载数据!教程代码很容易适应,我只能通过一些额外的实验来存储标题和细节数组。

因此,对于阅读这篇文章的人来说,他们正在努力解决NSUserDefault类型问题或者需要的不仅仅是存储字符串,请考虑花一两个小时玩核心数据。

以下是我读过的教程:

http://www.raywenderlich.com/85578/first-core-data-app-using-swift

如果您没有检查核心数据"

如果您没有检查核心数据"当您创建应用时,可以在之后添加,只需五分钟:

http://craig24.com/2014/12/how-to-add-core-data-to-an-existing-swift-project-in-xcode/

http://blog.zeityer.com/post/119012600864/adding-core-data-to-an-existing-swift-project

如何从核心数据列表中删除

Delete Data from Coredata Swift

答案 2 :(得分:11)

感谢@bploathttp://www.codingexplorer.com/nsuserdefaults-a-swift-introduction/

的链接

我发现对于一些基本的字符串存储,答案非常简单。

let defaults = NSUserDefaults.standardUserDefaults()

// Store
defaults.setObject("theGreatestName", forKey: "username")

// Receive
if let name = defaults.stringForKey("username")
{
    print(name)
    // Will output "theGreatestName"
}

我在这里总结了http://ridewing.se/blog/save-local-data-in-swift/

答案 3 :(得分:7)

使用NSCoding and NSKeyedArchiver对于NSUserDefaults过于复杂的数据来说是另一个很好的选择,但对于哪些CoreData来说太过分了。它还使您有机会更明确地管理文件结构,如果您想使用加密,这是很好的。

答案 4 :(得分:6)

对于Swift 4.0,这变得更加容易:

let defaults = UserDefaults.standard
//Set
defaults.set(passwordTextField.text, forKey: "Password")
//Get
let myPassword = defaults.string(forKey: "Password")

答案 5 :(得分:5)

对于Swift 3

UserDefaults.standard.setValue(token, forKey: "user_auth_token")
print("\(UserDefaults.standard.value(forKey: "user_auth_token")!)")

答案 6 :(得分:5)

Swift 3.0

设置者:本地存储

let authtoken = "12345"
    // Userdefaults helps to store session data locally 
 let defaults = UserDefaults.standard                                           
defaults.set(authtoken, forKey: "authtoken")

 defaults.synchronize()

Getter:本地存储

 if UserDefaults.standard.string(forKey: "authtoken") != nil {

//perform your task on success }

答案 7 :(得分:4)

对于因某些原因不喜欢处理UserDefaults的人,还有另一种选择 - NSKeyedArchiver& NSKeyedUnarchiver。它有助于使用archiver将对象保存到文件中,并将归档文件加载到原始对象。

// To archive object,
let mutableData: NSMutableData = NSMutableData()
let archiver: NSKeyedArchiver = NSKeyedArchiver(forWritingWith: mutableData)
archiver.encode(object, forKey: key)
archiver.finishEncoding()
return mutableData.write(toFile: path, atomically: true)

// To unarchive objects,
if let data = try? Data(contentsOf: URL(fileURLWithPath: path)) {
    let unarchiver = NSKeyedUnarchiver(forReadingWith: data)
    let object = unarchiver.decodeObject(forKey: key)
}

我编写了一个简单的实用程序来保存/加载本地存储中的对象,使用上面的示例代码。你可能想看到这个。 https://github.com/DragonCherry/LocalStorage

答案 8 :(得分:4)

快速5 +

所有答案都没有真正详细介绍默认的本地存储功能。它不仅可以做字符串,而且还能做

您可以直接从Apple文档中获得以下选项,以从默认值“获取”数据。

func object(forKey: String) -> Any?
//Returns the object associated with the specified key.

func url(forKey: String) -> URL?
//Returns the URL associated with the specified key.

func array(forKey: String) -> [Any]?
//Returns the array associated with the specified key.

func dictionary(forKey: String) -> [String : Any]?
//Returns the dictionary object associated with the specified key.

func string(forKey: String) -> String?
//Returns the string associated with the specified key.

func stringArray(forKey: String) -> [String]?
//Returns the array of strings associated with the specified key.

func data(forKey: String) -> Data?
//Returns the data object associated with the specified key.

func bool(forKey: String) -> Bool
//Returns the Boolean value associated with the specified key.

func integer(forKey: String) -> Int
//Returns the integer value associated with the specified key.

func float(forKey: String) -> Float
//Returns the float value associated with the specified key.

func double(forKey: String) -> Double
//Returns the double value associated with the specified key.

func dictionaryRepresentation() -> [String : Any]
//Returns a dictionary that contains a union of all key-value pairs in the domains in the search list.

以下是“设置”的选项

func set(Any?, forKey: String)
//Sets the value of the specified default key.

func set(Float, forKey: String)
//Sets the value of the specified default key to the specified float value.

func set(Double, forKey: String)
//Sets the value of the specified default key to the double value.

func set(Int, forKey: String)
//Sets the value of the specified default key to the specified integer value.

func set(Bool, forKey: String)
//Sets the value of the specified default key to the specified Boolean value.

func set(URL?, forKey: String)
//Sets the value of the specified default key to the specified URL.

如果要存储首选项不是大数据之类的东西,则设置这些选项是非常好的选择。

双重示例

设置:

let defaults = UserDefaults.standard
var someDouble:Double = 0.5
defaults.set(someDouble, forKey: "someDouble")

获取:

let defaults = UserDefaults.standard
var someDouble:Double = 0.0
someDouble = defaults.double(forKey: "someDouble")

其中一个吸气剂有趣的是 dictionaryRepresentation ,这个方便的吸气剂将接受所有数据类型,无论它们是什么,并将它们放入一个漂亮的字典中,您可以通过字符串名称和因为它的类型为'any',所以在您要求返回正确的数据类型时就可以使用。

您还可以使用func set(Any?, forKey: String)func object(forKey: String) -> Any?的setter和getter来存储自己的类和对象。

希望这可以进一步阐明UserDefaults类用于存储本地数据的功能。

关于应该存储多少和存储多少, Hardy_Germany 在此post上给出了很好的答案,下面是其中的引言

正如已经提到的许多人:我不知道任何SIZE限制 (物理内存除外)将数据存储在.plist中(例如 UserDefaults)。因此,这不是问题的多少。

真正的问题应该是您经常写新的/更改的内容 值...这与写入的电池消耗有关 原因。

IOS没有机会避免物理写入“磁盘”,如果单个 改变价值,只是为了保持数据完整性。关于用户默认值 这会导致整个文件重新写入磁盘。

这会打开“磁盘”的电源,并使其保持更长的时间,并且 防止IOS进入低功耗状态。

用户Mohammad Reza Farahani在post中提到的其他事项是userDefaults的异步同步性质。

设置默认值后,它会在您的内部同步更改 进程,并与持久性存储和其他进程异步。

例如,如果保存并快速关闭程序,您可能会注意到它没有保存结果,这是因为它是异步持久化的。您可能不会一直注意到这一点,因此,如果您打算在退出程序之前进行保存,则可能需要花一些时间来解决这个问题。

也许有人对此有一些不错的解决方案,可以在评论中分享?

答案 9 :(得分:0)

NsUserDefaults仅保存较小的变量大小。 如果要保存许多对象,可以将CoreData用作本机解决方案,或者我创建了一个库,该库可以帮助您像.save()函数一样轻松地保存对象。它基于SQLite。

SundeedQLite

查看并告诉我您的评论