Brandon Shega
Brandon Shega

Reputation: 769

iOS User preferences saving and updating

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?

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.

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.

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?

//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!

Upvotes: 0

Views: 188

Answers (1)

Rufel
Rufel

Reputation: 2660

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 *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];

Upvotes: 1

Related Questions