iOS用户首选项保存和更新

时间:2022-06-13 11:18:11

I think this question is going to be very difficult to ask so bear with me and if it doesn't make sense, just let me know.

我觉得这个问题很难问,所以请耐心等待,如果没有意义,请告诉我。

I will start by explaining the situation and then show some code. So I have an app that has an array of "default" settings to display on a user's dashboard. The user can modify these settings to enable or disable certain items that appear on their dashboard.

我将从解释情况开始,然后显示一些代码。所以我有一个应用程序,它有一组“默认”设置显示在用户的仪表板上。用户可以修改这些设置以启用或禁用其仪表板上显示的某些项目。

I want to be able to update the "default" settings and if I add a new item then it will automatically update the user's settings as well, but without overwriting their personal enable/disable setting.

我希望能够更新“默认”设置,如果我添加新项目,它也会自动更新用户的设置,但不会覆盖其个人启用/禁用设置。

So I have this array of dictionaries, the "default":

所以我有这个字典数组,“默认”:

dashboardItems = @[
                   @{
                       @"id" : @"1",
                       @"order" : @"0",
                       @"title" : @"Steps Traveled",
                       @"unit" : @"",
                       @"type" : HKQuantityTypeIdentifierStepCount,
                       @"sampleUnit" : @"count",
                       @"enabled" : @"1"
                   },
                   @{
                       @"id" : @"2",
                       @"order" : @"1",
                       @"title" : @"Flights Climbed",
                       @"unit" : @"",
                       @"type" : HKQuantityTypeIdentifierFlightsClimbed,
                       @"sampleUnit" : @"count",
                       @"enabled" : @"1"
                   },
                   @{
                       @"id" : @"3",
                       @"order" : @"2",
                       @"title" : @"Distance Traveled",
                       @"unit" : @"mi",
                       @"type" : HKQuantityTypeIdentifierDistanceWalkingRunning,
                       @"sampleUnit" : @"mi",
                       @"enabled" : @"1"
                   },
                   @{
                       @"id" : @"4",
                       @"order" : @"3",
                       @"title" : @"Active Calories",
                       @"unit" : @"",
                       @"type" : HKQuantityTypeIdentifierActiveEnergyBurned,
                       @"sampleUnit" : @"kcal",
                       @"enabled" : @"1"
                   },
                   @{
                       @"id" : @"5",
                       @"order" : @"4",
                       @"title" : @"Weight",
                       @"unit" : @"lbs",
                       @"type" : HKQuantityTypeIdentifierBodyMass,
                       @"sampleUnit" : @"lb",
                       @"enabled" : @"1"
                   },
                   @{
                       @"id" : @"6",
                       @"order" : @"5",
                       @"title" : @"Cycling",
                       @"unit" : @"mi",
                       @"type" : HKQuantityTypeIdentifierDistanceCycling,
                       @"sampleUnit" : @"mi",
                       @"enabled" : @"1"
                   },
                   @{
                       @"id" : @"7",
                       @"order" : @"6",
                       @"title" : @"Heart Rate",
                       @"unit" : @"BPM",
                       @"type" : HKQuantityTypeIdentifierHeartRate,
                       @"sampleUnit" : @"count/min",
                       @"enabled" : @"1"
                   },
                   @{
                       @"id" : @"8",
                       @"order" : @"7",
                       @"title" : @"BMI",
                       @"unit" : @"",
                       @"type" : HKQuantityTypeIdentifierBodyMassIndex,
                       @"sampleUnit" : @"count",
                       @"enabled" : @"1"
                   }
        ];

So the user can use a switch to change the enabled from a 1 to a 0 or vice-versa to turn on or off the item, with me so far?

因此,到目前为止,用户可以使用开关将启用从1更改为0,反之亦然,以打开或关闭项目?

When the user signs up the app saves the "default" settings to NSUserDefaults and also to the live server to back up in case the user ever deletes the app.

当用户注册应用程序时,将“默认”设置保存到NSUserDefaults,并将实时服务器保存,以备用户删除应用程序。

If the user logs out or deletes the app, on next login we check to see if they currently have and NSUserDefaults saved, if not we pull from the server.

如果用户注销或删除应用程序,则在下次登录时我们会检查他们当前是否已保存NSUserDefaults,如果不是,则从服务器提取。

Then I compare the 2 arrays to see if any items were changed or added to the "defaults", is this the best way to go about doing it?

然后我比较2个数组,看看是否有任何项目被更改或添加到“默认值”,这是最好的方法吗?

//here we need to check if the user does not have any preferences saved, if not pull them from Parse.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

NSMutableArray *dashboardItems = [defaults objectForKey:@"dashboardItems"];

if (dashboardItems == nil) {

    //user has no preferences so load them in
    dashboardItems = [NSJSONSerialization JSONObjectWithData:[user[@"preferences"] dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];

    [defaults setObject:dashboardItems forKey:@"dashboardItems"];
    [defaults synchronize];

}

//compare current preferences against default to see if any new items were changed
NSArray *defaultPreferences = [[PreferencesManager sharedManager] dashboardItems];

for (NSDictionary *item in defaultPreferences) {

    for (NSDictionary *userItem in dashboardItems) {

        if ([item[@"id"] isEqualToString:userItem[@"id"]]) {

            //we have a match, compare name and change if necessary
            if (![item[@"title"] isEqualToString:userItem[@"title"]]) {

                //set user's item title to default title
                [userItem setValue:item[@"title"] forKey:@"title"];

            }

        } else {

            //we did not find this in user preferences, so add it
            [dashboardItems addObject:item];

        }

    }


}

//save defaults
[defaults setObject:dashboardItems forKey:@"dashboardItems"];
[defaults synchronize];

If I need to clarify anything further, please just let me know.

如果我需要进一步澄清,请告诉我。

Thanks!

1 个解决方案

#1


I would start by getting all default settings, then replace those that has a match in the stored user settings:

我首先获取所有默认设置,然后替换存储的用户设置中匹配的设置:

NSMutableArray *defaultSettings = [@[] mutableCopy];
NSArray *userSettings = @[];
for (NSInteger i = 0; i < defaultSettings.count; i++) {
    NSDictionary *setting = defaultSettings[i];
    NSInteger index = [userSettings indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        NSDictionary *userSetting = obj;
        *stop = [setting[@"title"] isEqualToString:userSetting[@"title"]];
        return *stop;
    }];
    if (index != NSNotFound) {
        // Found matching setting
        defaultSettings[i] = userSettings[index];
    }
}

[defaults setObject:defaultSettings forKey:@"defaultSettings"];
[defaults synchronize];

But if I were you, I'd use a NSDictionary of NSDictionary, and use the key as the ID. It would made the same process a lot easier:

但如果我是你,我会使用NSDictionary的NSDictionary,并使用密钥作为ID。它会使同一个过程变得更加容易:

NSDictionary *defaultSettings = @{
                                  @"1": @{@"order": @"0", @"title": @"Steps traveled", @"enabled": @"0"},
                                  @"2": @{@"order": @"1", @"title": @"Flights Climbed", @"enabled": @"0"},
                                  @"3": @{@"order": @"2", @"title": @"Distance Traveled", @"enabled": @"0"}
                                  };
NSMutableDictionary *mutableDefaultSettings = [defaultSettings mutableCopy];
NSDictionary *userSettings = @{
                               @"2": @{@"order": @"1", @"title": @"Flights Climbed", @"enabled": @"1"}
                               };

for (NSString *id in userSettings.allKeys) {
    mutableDefaultSettings[id] = userSettings[id];
}

[defaults setObject:mutableDefaultSettings forKey:@"dashboardItems"];
[defaults synchronize];

#1


I would start by getting all default settings, then replace those that has a match in the stored user settings:

我首先获取所有默认设置,然后替换存储的用户设置中匹配的设置:

NSMutableArray *defaultSettings = [@[] mutableCopy];
NSArray *userSettings = @[];
for (NSInteger i = 0; i < defaultSettings.count; i++) {
    NSDictionary *setting = defaultSettings[i];
    NSInteger index = [userSettings indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        NSDictionary *userSetting = obj;
        *stop = [setting[@"title"] isEqualToString:userSetting[@"title"]];
        return *stop;
    }];
    if (index != NSNotFound) {
        // Found matching setting
        defaultSettings[i] = userSettings[index];
    }
}

[defaults setObject:defaultSettings forKey:@"defaultSettings"];
[defaults synchronize];

But if I were you, I'd use a NSDictionary of NSDictionary, and use the key as the ID. It would made the same process a lot easier:

但如果我是你,我会使用NSDictionary的NSDictionary,并使用密钥作为ID。它会使同一个过程变得更加容易:

NSDictionary *defaultSettings = @{
                                  @"1": @{@"order": @"0", @"title": @"Steps traveled", @"enabled": @"0"},
                                  @"2": @{@"order": @"1", @"title": @"Flights Climbed", @"enabled": @"0"},
                                  @"3": @{@"order": @"2", @"title": @"Distance Traveled", @"enabled": @"0"}
                                  };
NSMutableDictionary *mutableDefaultSettings = [defaultSettings mutableCopy];
NSDictionary *userSettings = @{
                               @"2": @{@"order": @"1", @"title": @"Flights Climbed", @"enabled": @"1"}
                               };

for (NSString *id in userSettings.allKeys) {
    mutableDefaultSettings[id] = userSettings[id];
}

[defaults setObject:mutableDefaultSettings forKey:@"dashboardItems"];
[defaults synchronize];