覆盖从 NSUserDefaults 加载的 NSMutableArray

Overwriting NSMutableArray loaded from NSUserDefaults

所以我在覆盖存储在 NSUSerDefaults 中的数组时遇到了实际问题。 基本上我有一个包含 100 个项目的清单(由数组中的布尔值定义(目前实际上是字符串)),如果每个项目都被选中我需要保存,所以当应用程序加载时,清单保持在应用程序之前已关闭。

我会尽力解释当前的流程。

在 ViewDidLoad 中,我创建了空数组 boolArrayOfCheckList:

boolArrayOfCheckList = [[NSMutableArray alloc] initWithCapacity:100];
    for (NSInteger i = 0; i < 100; i++){
        [boolArrayOfCheckList addObject:[NSString stringWithFormat:@"NO"]];
    }

所以目前,由于 100 个索引设置为 @"NO"

,数组建议未检查任何项目

然后我将数组从 NSUserDefaults 加载到上面的数组中:

NSMutableArray *boolArrayOfCheckList = [[NSUserDefaults standardUserDefaults] objectForKey:@"myBoolArray"];

然后我根据与开关按钮关联的数组索引值设置开关按钮的状态(例如这是按钮 1,存储在索引 0):

if([[boolArrayOfCheckList objectAtIndex:0] isEqualToString:@"YES"]){
   [switchButton1 setOn:YES];  //array says YES, so button is on
}
else {
   [switchButton1 setOn:NO];  //array says NO, so remains off
}

这似乎在第一次运行时有效,并保存了数组。但是如果数组中的元素被更改,问题就来了,因为它不保存任何以前存储的更改...

如果按下另一个开关,例如开关 2:

- (IBAction)Switch2:(id)sender {
    if([switchButton2 isOn]){
        [boolArrayOfCheckList replaceObjectAtIndex:1 withObject:[NSString stringWithFormat:@"YES"]];
        [self SaveDataWhenArrayInBoolArrayIsChanged]; //save data to YES
    }
    else{
        [boolArrayOfCheckList replaceObjectAtIndex:1 withObject:[NSString stringWithFormat:@"NO"]];
        [self SaveDataWhenArrayInBoolArrayIsChanged]; //save data to NO
    }
}

如果按下一个按钮,改变按钮的状态,SaveDataWhenArrayInBoolArrayIsChanged 方法被调用,并像这样保存到 NSUserDefaults:

[[NSUserDefaults standardUserDefaults] setObject:boolArrayOfCheckList forKey:@"myBoolArray"];
[[NSUserDefaults standardUserDefaults] synchronize];

但出于某种原因,例如,如果我在应用程序启动时打开了按钮 1、3 和 5,然后我单击按钮 4 以打开,使 1、3、4、5 按钮打开,当我返回,只有按钮 4 处于打开状态,它会重置按钮 1、3 和 5 :(

有没有更简单的解决方案?或者我是否需要更改我的实现或制作数组的副本并保存某些内容的副本?如果是这样,如何?谢谢。

更新

我关注了这些人 post HERE

我想我可能已经解决了这个问题,当从 NSUserDefaults 加载数组时,我将它加载到一个临时数组(因为它必须是不可变的),然后将临时数组复制到空的 boolArrayOfChecklist(这是一个新的可变数组)像这样:

NSMutableArray *boolArrayOfCheckList_Temp = (NSMutableArray *)[[NSUserDefaults standardUserDefaults] objectForKey:@"myBoolArray"];
boolArrayOfCheckList = [NSMutableArray arrayWithArray:boolArrayOfCheckList_Temp];

不确定那是我应该做的,但它允许我编辑保存的数组,保存它并重新加载它而无需重置以前的 elements/indexes。

所以它似乎在工作......我知道我不应该使用字符串,我应该包装 bools 或使用 NSNumber 但我不确定这些如何与 MutableArrays 一起工作并比较它们......我'我确定有比我这样做更好的原因,但我仍然是 learning/a 初学者...不过,如果有人愿意向我展示,那就太好了 :)

您应该使用 NSNumber,那么您无需担心比较本身,因为您只需提取标志值并将其设置为开关状态。

此外,您不想显式创建数组并尝试将其从默认值恢复。相反,您应该注册默认值并加载默认值(请注意,如果将来要迁移的项目数量发生变化,您将需要编写代码...):

NSMutableArray  *checklistDefaults = [[NSMutableArray alloc] initWithCapacity:100];
for (NSInteger i = 0; i < 100; i++){
    [checklistDefaults addObject:@NO];
}

[[NSUserDefaults standardUserDefaults] registerDefaults:@{@"myBoolArray" : checklistDefaults}];

然后加载到你的数组中使用:

NSMutableArray *boolArrayOfCheckList = [[[NSUserDefaults standardUserDefaults] objectForKey:@"myBoolArray"] mutableCopy];

然后使用并更新值:

[switchButton1 setOn:[[boolArrayOfCheckList objectAtIndex:XX] boolValue]];

BOOL currentValue = [[boolArrayOfCheckList objectAtIndex:XX] boolValue];
[boolArrayOfCheckList replaceObjectAtIndex:XX withObject:@( !currentValue )];