【发布时间】:2011-10-26 21:29:44
【问题描述】:
我将存储一些字符串(可能是 10-20)。我不确定是否应该使用 NSUserDefaults 来保存它们,或者将它们写到 plist 中。什么被认为是最佳实践? NSUserDefaults 似乎代码行数更少,因此实现起来更快。
我想补充一点,这些字符串值将由用户添加/删除。
【问题讨论】:
标签: iphone objective-c cocoa-touch plist nsuserdefaults
我将存储一些字符串(可能是 10-20)。我不确定是否应该使用 NSUserDefaults 来保存它们,或者将它们写到 plist 中。什么被认为是最佳实践? NSUserDefaults 似乎代码行数更少,因此实现起来更快。
我想补充一点,这些字符串值将由用户添加/删除。
【问题讨论】:
标签: iphone objective-c cocoa-touch plist nsuserdefaults
像这样持久化数据的推荐方法是使用 Core Data。虽然 NSUserDefaults 可用于存储或多或少的任何内容,但它只应用于存储首选项。
【讨论】:
这取决于您要存储什么以及为什么。 NSUserDefaults 用于存储用户偏好。您可以尝试将其用于其他用途,但您可能不应该这样做。
否则,如果您的需求很简单,则 plist 文件非常简单。您还可以使用核心数据或提出自己的文件格式。一般来说,我将 plist 用于简单的任务,然后转移到核心数据来处理更复杂的任务。
【讨论】:
如果您要存储 10 到 20 个字符串并且寻找的代码行数不多,那么核心数据的开销肯定会太大。我建议使用 plist。代码不多:
NSURL *plistURL = [[NSBundle mainBundle] URLForResource:@"MyStrings" withExtension:@"plist"];
NSArray *stringArray = [NSArray arrayWithContentsOfURL:plistURL];
【讨论】:
NSUserDefaults 会将用户首选项存储到 Library/Preferences 文件夹中的文件中。从理论上讲,它仅用于存储一些应用程序/用户属性。
Plist 文件对于管理单个文件很有用。如果你需要管理更多,你应该使用 Coredata。 plist 文件的大小没有限制。否则你必须小心 plist 文件,因为当你需要保存或读取它时,文件的全部内容将被加载到内存中。
【讨论】:
我假设是一个数组,但它也适用于字典。
Userdefaults、Core Data 和 Plists 都可以读/写,但是如果你使用 plist,你需要注意你把它放在什么目录下。请参阅下面的 plist 部分。
Core Data 我认为这太过分了,它只是字符串。 当您想要持久化更复杂的对象时应该使用它。
NSUserDefaults:
虽然它应该只存储用户设置,但它非常快速且易于操作。 要将它们写入用户默认值:
NSArray *stringsArray = [[NSArray alloc] arrayWithObjects: string1, string2, string3, nil];
[[NSUserDefaults standardUserDefaults] setObject:stringsArray forKey:@"MyStrings"];
[[NSUserDefaults standardUserDefaults] synchronize];
从用户默认值中读取:
NSArray *stringsArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"MyStrings"];
列表:
如果要修改您的字符串,您将需要写入和读取 plist,但您不能写入应用的资源。
要有一个读/写plist首先找到文档目录
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *stringsPlistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Strings.plist"];
创建数组(我假设字符串是 string1,...)
NSArray *stringsArray = [[NSArray alloc] arrayWithObjects: string1, string2, string3, nil];
写入文件
[stringsArray writeToFile:stringsPlistPath atomically:YES];
阅读 plist:
找到文档目录
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *stringsPlistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Strings.plist"];
阅读:
NSArray *stringsArray = [NSArray arrayWithContentsOfFile:stringsPlistPath];
【讨论】:
如果字符串不仅仅是可以进入 NSUserDefaults 的用户设置,则使用 plist 是存储字符串的好选择。如前所述,使用 plist 时,您必须将 plist 存储在 Documents 目录中才能写入,因为您无法写入自己应用程序的资源。当我第一次了解到这一点时,我不清楚您自己的应用程序的 Bundle 目录与 Documents 目录的位置,所以我想我会在这里发布示例代码,首先复制一个名为“Strings.plist”的 plist(即您已经在自己的应用程序的 Bundle 目录中)复制到 Documents 目录,然后对其进行写入和读取。
// Make a path to the plist in the Documents directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *stringsPlistPathIndDoc = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Strings.plist"];
// Make a path to the plist in your app's Bundle directory
NSString *stringsPlistPathInBundle = [[NSBundle mainBundle] pathForResource:@"Strings" ofType:@".plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check first that you haven't already copied this plist to the Documents directory
if (![fileManager fileExistsAtPath:stringsPlistPathIndDoc])
{
NSError *error;
// Copy the plist from the Bundle directory to the Documents directory
[fileManager copyItemAtPath:stringsPlistPathInBundle toPath:stringsPlistPathIndDoc error:&error];
}
// Write your array out to the plist in the Documents directory
NSMutableArray *stringsArray = [[NSMutableArray alloc] initWithObjects:@"string1", @"string2", @"string3", nil];
[stringsArray writeToFile:stringsPlistPathIndDoc atomically:YES];
// Later if you want to read it:
stringsArray = [[NSMutableArray alloc] initWithContentsOfFile:stringsPlistPathIndDoc];
【讨论】:
iOS 最终将所有 NSUserDefaults 数据存储到 plist 文件中。因此,如果这是您关心的问题,它不会影响性能。我个人更喜欢使用NSUserDefaults 处理小数据,使用 plist 处理相对较大的数据集。
注意:切勿将任何敏感信息存储在 NSUserDefaults 中,因为任何人都可以看到这些数据。
【讨论】:
使用 .plist
向 plist 写入值
NSURL *plistURL = [[NSBundle mainBundle] URLForResource:@"settings" withExtension:@"plist"];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfURL:plistURL];
[dict setValue:@"value" forKey:@"key"];
[dict writeToURL:plistURL atomically:YES];
从 plist 中读取一个值
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfURL:plistURL];
NSString *myValue = [dict valueForKey:@"key"];
【讨论】:
NSUSerDefaults确实实现起来很快,但是主要是随着你的应用程序的增长,你想要存储的越来越多,我直接去找了plist文件。
大多数情况下,人们想要存储一些东西的列表,所以这里是我关于如何使用 NSDictionary 做到这一点的分享。这不需要你先创建一个plist文件,它会在第一次创建保存一些东西
xcode 7 测试版,Swift 2.0
保存
func SaveItemFavorites(items : Array<ItemFavorite>) -> Bool
{
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let docuDir = paths.firstObject as! String
let path = docuDir.stringByAppendingPathComponent(ItemFavoritesFilePath)
let filemanager = NSFileManager.defaultManager()
let array = NSMutableArray()
for var i = 0 ; i < items.count ; i++
{
let dict = NSMutableDictionary()
let ItemCode = items[i].ItemCode as NSString
dict.setObject(ItemCode, forKey: "ItemCode")
//add any aditional..
array[i] = dict
}
let favoritesDictionary = NSDictionary(object: array, forKey: "favorites")
//check if file exists
if(!filemanager.fileExistsAtPath(path))
{
let created = filemanager.createFileAtPath(path, contents: nil, attributes: nil)
if(created)
{
let succeeded = favoritesDictionary.writeToFile(path, atomically: true)
return succeeded
}
return false
}
else
{
let succeeded = notificationDictionary.writeToFile(path, atomically: true)
return succeeded
}
}
来自文档的小注释:
NSDictionary.writeToFile(path:atomically:)
此方法在写出文件之前递归地验证所有包含的对象都是属性列表对象(
NSData、NSDate、NSNumber、NSString、NSArray或NSDictionary的实例),如果所有对象都不是属性列表对象,则返回 NO,因为结果文件不是有效的属性列表。
所以你在dict.SetObject() 设置的任何东西都应该是上述类型之一。
加载中
private let ItemFavoritesFilePath = "ItemFavorites.plist"
func LoadItemFavorites() -> Array<ItemFavorite>
{
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let docuDir = paths.firstObject as! String
let path = docuDir.stringByAppendingPathComponent(ItemFavoritesFilePath)
let dict = NSDictionary(contentsOfFile: path)
let dictitems : AnyObject? = dict?.objectForKey("favorites")
var favoriteItemsList = Array<ItemFavorite>()
if let arrayitems = dictitems as? NSArray
{
for var i = 0;i<arrayitems.count;i++
{
if let itemDict = arrayitems[i] as? NSDictionary
{
let ItemCode = itemDict.objectForKey("ItemCode") as? String
//get any additional
let ItemFavorite = ItemFavorite(item: ItemCode)
favoriteItemsList.append(ItemFavorite)
}
}
}
return favoriteItemsList
}
【讨论】: