【问题标题】:Store an array where I only save one member each time?存储一个数组,我每次只保存一个成员?
【发布时间】:2015-04-18 05:41:07
【问题描述】:

我想存储一个数组,以便它在启动时可用。数组中的每一项代表一个列表中的一项,在存入数组之前会转换成JSON格式。

我一直将它保存到 NSUserDefaults,但我不想每次我想更改其中的单个项目时都将整个数组保存到 NSUserDefaults。理想情况下,我只需在数组内部更改该值,而无需更改其他值。而且我还需要在数组中添加和删除项目,而且我不想仅仅为了这样做而保存整个数组。

有没有更有效的方法?

现在,我一直在解决这个问题,将每个项目保存到 NSUserDefaults 下的自己的标识符下,以及一个数组,每个标识符都有正确的顺序。不过,这正在成为一个复杂的解决方案,存在问题。

【问题讨论】:

  • 为什么不使用Array 而不是Dictionary?这包含键值对,因此字典中的每个键都是唯一的,然后您也可以保存该键的值。看起来更符合你的追求。
  • 如果您对增量更改感兴趣,这就是 CoreData 的真正用途。
  • 除非您在谈论数十万个条目或数组更改,否则真的不值得担心效率。 “过早的优化是万恶之源”。但字典绝对是更好的方法。
  • @Popeye 字典的问题在于它没有被排序。这是一个有序列表。但是,它并没有解决我的问题 - 每次我保存它时,我仍然保存该字典中的每个项目。
  • 我们不关心字典的顺序,我们只关心当你对字典进行allKeys 调用时,我们想要的顺序是键。我会看看并添加一个部分,用于获取所有键并将它们排序到我的答案中

标签: ios objective-c local-storage nsuserdefaults


【解决方案1】:

为什么不使用NSArray 而不是使用NSDictionary 来保存您的数据,因为这将使您在需要时更容易获取数据并且更容易转换为JSON

所以我会做类似的事情:

// Few constants for keys
NSString const *itemsListKey = @"FruitItems";
NSString const *applesKey = @"Apples";
NSString const *bananasKey = @"Bananas";

创建一个新字典并将其添加到我们的NSUserDefaults

NSMutableDictionary *items = [[NSMutableDictionary alloc] init];
[items setObject:5 forKey:applesKey];
[items setObject:2 forKey:bananasKey];

[[NSUserDefaults standardUserDefaults] setObject:items forKey:itemsListKey];
[[NSUserDefaults standardUserDefaults] synchronize];

在我们的NSUserDefaults中检索现有字典并修改当前字典

// The dictionary retrieved isn't mutable so we need to get a mutable copy of it.
NSMutableDictionary *itemsRetrieved = [[[NSUserDefaults standardDefaults] dictionaryForKey:itemsListKey] mutableCopy];
// Lets update our Apples value
[itemsRetrieved setObject:9 forKey:applesKey];

// Set the dictionary back into NSUserDefaults
[[NSUserDefaults standardUserDefaults] setObject:items forKey:itemsListKey];
[[NSUserDefaults standardUserDefaults] synchronize];

您会注意到这两种不同的方法之间没有太大的区别,因此您可以将其集成到如下的一种方法中。

// Obviously this constant being the key to your dictionary
NSString const *itemsListKey = @"itemsList"; 

- (void)updateItemsForKey:(NSString *)key withValue:(NSInteger)value
{
    NSMutableDictionary *items [[NSMutableDictionary alloc] init];
    if ([[NSUserDefaults standardDefaults] dictionaryForKey:itemsListKey] != nil) {
        // If the key already exist in NSUserDefaults reallocate it 
        // to the one that exists.
        items = [[[NSUserDefaults standardDefaults] dictionaryForKey:itemsListKey] mutableCopy];
    }

    [itemsRetrieved setObject:value forKey:key]; 

    // Assign the dictionary back into NSUserDefaults
    [[NSUserDefaults standardUserDefaults] setObject:items forKey:itemsListKey];
    [[NSUserDefaults standardUserDefaults] synchronize];
} 

编辑 - 根据他们希望订购的 cmets。

真的,我们不在乎NSDictionary 是否已排序。如果我们希望对象按排序顺序排列,我们可以在执行allKeys 调用时将字典的键排序为排序顺序。

NSArray *orderedKeys =  [[items allKeys] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    return [(NSString *)obj1 compare:(NSString *)obj2 options:NSNumericSearch];
}];

上面的代码会给你一个按数字排序的数组,然后你循环遍历orderedKeys数组以按照你想要的顺序得到你想要的值:

for (NSString *key in orderedKeys) {
    id objectFromDict = [items objectForKey:key];
    // Do whatever you want with that object.
}

【讨论】:

    【解决方案2】:

    保存整个数组有什么问题?如果要编辑一项,请从NSUserDefaults 中取出数组(创建一个可变副本),更改相应的项,然后将数组保存回来。

    【讨论】:

    • 对不同的项目使用跨多个线程意味着数据可能会被覆盖。而且,因为每一项都是字典,所以我每次都会保存一大堆数据。
    猜你喜欢
    • 2017-12-04
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多