kschins
kschins

Reputation: 1224

Initializing NSDictionary

The following is in my .h file:

    NSDictionary *originalValues;
    @property (nonatomic, retain) NSDictionary *originalValues;

This is the .m file to init the NSDictionary.

@synthesize originalValues;

- (void)viewDidLoad {

// copy original values when view loaded
originalValues = [[NSDictionary alloc] initWithObjectsAndKeys:place.city, @"city", place.cuisine, @"cuisine",
                place.latitude, @"latitude", place.longitude, @"longitude", place.name, @"name", place.rating,
                @"rating", place.state, @"state", place.street, @"street", place.telephone, @"telephone",
                place.timesVisited, @"times visited", place.uppercaseFirstLetterOfName, @"first letter", 
                place.website, @"website", place.zipcode, @"zipcode", nil];
}

The problem is only the first four objects and keys are getting added. After that, they are not being added to the dictionary starting with place.name, @"name". I did a NSLog on the entire dictionary and the only things outputted were the first four values like I mentioned so then II did an NSLog on place.name and it is outputting a value so I know something should also be outputted for this key/value pair. Is there something I am missing here? I'm curious why all of the values are not being initially added to the NSDictionary?

Upvotes: 28

Views: 77704

Answers (3)

BootMaker
BootMaker

Reputation: 1647

To avoid accidental nil in any dictionary the best solution would be if you combine the two technics using the literal and the ternary operator like

self.originalValues = @{ @"city" : (place.city ?: @"city"), 
                      @"latitude" : (place.latitude  ?: [NSNull null]),
                      // etc.
                       };

Note:

(anyValueOrVariable ?: @"anyOtherValueOrVariable")

is an abbrevation and means same as

(anyValueOrVariable != 0) ? anyValueOrVariable : @"anyOtherValueOrVariable"

Upvotes: 8

TotoroTotoro
TotoroTotoro

Reputation: 17622

If one of the objects is nil, you can catch that much faster if you use the new literal syntax for initializing an NSDictionary (below). This syntax is not only shorter, but also more robust: you'll actually get a runtime error if one of your objects is nil, instead of silently continuing execution with the incomplete data.

originalValues = @{ @"city"     : place.city, 
                    @"latitude" : place.latitude,
                    // etc.
                  };

Upvotes: 66

Joe
Joe

Reputation: 57179

The reason why they are not being added is because an object is nil which marks the end of the dictionary. You need to be sure that each object is not nil and if it is you can use [NSNull null] in place of it. Also use self.originalValues = ... for proper memory management. Just make sure what ever uses the dictionary checks/can handle NSNull values.

Example using gnu ternary extension:

self.originalValues = [[NSDictionary alloc] initWithObjectsAndKeys:
                         place.city ?: [NSNull null], @"city",
                         place.cuisine ?: [NSNull null], @"cuisine",
                         place.latitude ?: [NSNull null], @"latitude",
                         place.longitude ?: [NSNull null], @"longitude",
                         place.name ?: [NSNull null], @"name",
                         place.rating ?: [NSNull null], @"rating",
                         place.state ?: [NSNull null], @"state",
                         place.street ?: [NSNull null], @"street",
                         place.telephone ?: [NSNull null], @"telephone",
                         place.timesVisited ?: [NSNull null], @"times visited",
                         place.uppercaseFirstLetterOfName ?: [NSNull null], @"first letter", 
                         place.website ?: [NSNull null], @"website",
                         place.zipcode ?: [NSNull null], @"zipcode",
                         nil];

Upvotes: 50

Related Questions