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

Nic*_*ing 132 nsuserdefaults ios swift

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

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

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

Wez*_*Wez 185

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

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

struct defaultsKeys {
    static let keyOne = "firstStringKey"
    static let keyTwo = "secondStringKey"
}
Run Code Online (Sandbox Code Playgroud)

Swift 2.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
}
Run Code Online (Sandbox Code Playgroud)

Swift 3.0和4.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
}
Run Code Online (Sandbox Code Playgroud)

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

  • 很好的例子.这可能应该是枚举而不是结构. (7认同)
  • 这是一个奇怪的枚举实现,如果你只有静态常量,它也可能是一个结构. (3认同)

Dav*_*e G 51

他们说使用NSUserDefaults

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

NSUserDefaults在功能上也是有限的

进一步阅读揭示了NSUserDefaults的读/写操作如何真正迫使应用程序一次性读取/写入所有内容,因此效率不高.然后我了解到检索数组并不是直截了当的.我意识到如果你存储的不仅仅是一些字符串或布尔值,NSUserDefaults确实不太理想.

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

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

使用核心数据

所以我忽略了关于Core Data的警告是一个更难解决的问题,并开始阅读.在三个小时内我就开始工作了.我将我的表数组保存在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

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

从Coredata Swift中删除数据

  • 将数据保存到Documents目录或应用程序沙盒目录中其他位置的某个.plist文件的中间位置. (5认同)
  • 我会说:使用NSUserDefaults存储首选项(这就是名称的意思),存储持久性和/或敏感数据的钥匙串,_very basic_ app生成数据的.plist文件的自定义方案,以及更重的东西的CoreData . (3认同)

Nic*_*ing 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"
}
Run Code Online (Sandbox Code Playgroud)

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


Pat*_*nch 9

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


Lev*_*ies 7

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

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


Jos*_*han 7

斯威夫特 5+

\n\n

没有一个答案真正详细介绍了默认内置的本地存储功能。它的功能远不止字符串。

\n\n

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

\n\n
func object(forKey: String) -> Any?\n//Returns the object associated with the specified key.\n\nfunc url(forKey: String) -> URL?\n//Returns the URL associated with the specified key.\n\nfunc array(forKey: String) -> [Any]?\n//Returns the array associated with the specified key.\n\nfunc dictionary(forKey: String) -> [String : Any]?\n//Returns the dictionary object associated with the specified key.\n\nfunc string(forKey: String) -> String?\n//Returns the string associated with the specified key.\n\nfunc stringArray(forKey: String) -> [String]?\n//Returns the array of strings associated with the specified key.\n\nfunc data(forKey: String) -> Data?\n//Returns the data object associated with the specified key.\n\nfunc bool(forKey: String) -> Bool\n//Returns the Boolean value associated with the specified key.\n\nfunc integer(forKey: String) -> Int\n//Returns the integer value associated with the specified key.\n\nfunc float(forKey: String) -> Float\n//Returns the float value associated with the specified key.\n\nfunc double(forKey: String) -> Double\n//Returns the double value associated with the specified key.\n\nfunc dictionaryRepresentation() -> [String : Any]\n//Returns a dictionary that contains a union of all key-value pairs in the domains in the search list.\n
Run Code Online (Sandbox Code Playgroud)\n\n

以下是“设置”的选项

\n\n
func set(Any?, forKey: String)\n//Sets the value of the specified default key.\n\nfunc set(Float, forKey: String)\n//Sets the value of the specified default key to the specified float value.\n\nfunc set(Double, forKey: String)\n//Sets the value of the specified default key to the double value.\n\nfunc set(Int, forKey: String)\n//Sets the value of the specified default key to the specified integer value.\n\nfunc set(Bool, forKey: String)\n//Sets the value of the specified default key to the specified Boolean value.\n\nfunc set(URL?, forKey: String)\n//Sets the value of the specified default key to the specified URL.\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果要存储诸如首选项之类的内容而不是大型数据集,那么这些都是非常好的选择。

\n\n

双示例

\n\n

环境:

\n\n
let defaults = UserDefaults.standard\nvar someDouble:Double = 0.5\ndefaults.set(someDouble, forKey: "someDouble")\n
Run Code Online (Sandbox Code Playgroud)\n\n

得到:

\n\n
let defaults = UserDefaults.standard\nvar someDouble:Double = 0.0\nsomeDouble = defaults.double(forKey: "someDouble")\n
Run Code Online (Sandbox Code Playgroud)\n\n

其中一个 getter 的有趣之处在于DictionaryRepresentation,这个方便的 getter 将获取所有数据类型,无论它们是什么,并将它们放入一个很好的字典中,您可以通过它的字符串名称访问该字典,并在以下情况下给出正确的相应数据类型:你要求取回它,因为它的类型是 \ 'any\'

\n\n

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

\n\n

希望这能更多地阐明 UserDefaults 类存储本地数据的功能。

\n\n

关于应该存储多少以及存储频率,Hardy_Germany在这篇文章中给出了很好的答案,这里引用了其中的一段话

\n\n
\n

正如许多人已经提到的:我不知道在 .plist 中存储数据有任何大小限制(物理内存除外)(例如 UserDefaults)。所以这不是“多少”的问题。

\n\n

真正的问题应该是您多久写入一次新的/更改的值...这与写入将导致的电池消耗有关。

\n\n

如果单个值发生更改,IOS 无法避免物理写入“磁盘”,只是为了保持数据完整性。关于 UserDefaults\n 这会导致整个文件重写到磁盘。

\n\n

这会为“磁盘”供电并使其保持较长时间的供电状态,并\n 防止 IOS 进入低功耗状态。

\n
\n\n

用户 Mohammad Reza Farahani 在这篇文章中提到的其他值得注意的事情是userDefaults 的异步同步性质。

\n\n
\n

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

\n
\n\n

例如,如果您保存并快速关闭程序,您可能会注意到它没有保存结果,这是因为它是异步持久的。您可能不会一直注意到这一点,因此如果您计划在退出程序之前保存,您可能需要给它一些时间来完成。

\n\n

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

\n


Rav*_*wat 6

Swift 3.0

Setter:本地存储

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

 defaults.synchronize()
Run Code Online (Sandbox Code Playgroud)

Getter:本地存储

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

//perform your task on success }
Run Code Online (Sandbox Code Playgroud)

  • 你不应该像UserDefaults中的authtoken一样保存smth ..请使用Keychain (2认同)

小智 5

对于Swift 3

UserDefaults.standard.setValue(token, forKey: "user_auth_token")
print("\(UserDefaults.standard.value(forKey: "user_auth_token")!)")
Run Code Online (Sandbox Code Playgroud)