HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Comparing 2 arrays of dictionaries and saving user preferences

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
preferencesarrayscomparinguseranddictionariessaving

Problem

I will start by explaining the situation and then show some code. 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.

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",

Solution

//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"];

}


This sort of code is a bit redundant, and also shows inconsistency between using and not using the modern syntax for dictionaries.

We can rewrite it as simply:

userItem[@"title"] = item[@"title"];


We don't need to check whether or not they're different titles.

The amount of vertical white space in your code is excessive and distracting. We can eliminate most of these empty lines. I don't think they add anything other than making me work my scroll wheel a bit more.

Calling synchronize on NSUserDefaults is largely unnecessary. NSUserDefaults loads the defaults into memory. When you set a value, it sets it in memory (but doesn't save it to permanent storage yet). Next time you access the value for that key, it will serve you the value you set (which it has in memory), regardless of whether or not it has taken the time to write it to permanent storage yet or not.

NSUserDefaults tries to find opportune, low-cost times to write to permanent storage when it knows it has pending changes. Worst case scenario, it will be sure to write to permanent storage just before your app is exited.

The only way to lose something that is in NSUserDefaults in memory but not yet written to permanent storage is if your app crashes without NSUserDefaults having an opportunity to write.

All that calling synchronize does is make your app take the time to force NSUserDefaults to write its current state to permanent storage. That's it. It's completely unnecessary, and your app shouldn't be crashing and losing its temporary storage stuff anyway.

Code Snippets

//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"];

}
userItem[@"title"] = item[@"title"];

Context

StackExchange Code Review Q#89976, answer score: 7

Revisions (0)

No revisions yet.