1

I have a certain NSDictionary with couple of keys but they go much in dept in hirerchy such as:

  1. Person:
    • Gender:
      • Name:
        • Address:
  2. Location:

So you can see if I insert this in nsdictionary, initially I just have two keys as "Person" and "Location", however I am trying to iterate in each one of the keys to check for null value and set it to @"" empty string.

Does anyone know how to iterate through such dept?

Thanks

topgun
  • 2,463
  • 8
  • 31
  • 46

5 Answers5

6
  • you can't store a nil in an NSDictionary. Either you'll be looking for [NSNull null] or you'll be looking for dictionaries that lack the keys you are looking for....

  • enumerateKeysAndObjectsUsingBlock: is faster than for( ... in ...).

  • if you are modifying the contents of the dictionaries, you must use mutable dictionaries. If you are unarchiving from a property list, there are options for creating mutable containers with immutable nodes (which is probably what you want).

Recurse is the answer, though non of the answers that show recursion are correct.

- (void)filterMutableDictionary:(NSMutableDictionary*)aDictionary
{
      // check if aDictionary is missing any keys here
      if (![aDictionary objectForKey:@"DesiredKey"]) {
          ... fill in key/value here ...
      }

      // enumerate key/values, filtering appropriately, recursing as necessary
      [aDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
            if ([value isKindOfClass: [NSMutableDictionary class]]) {
                [self filterMutableDictionary: value];
            } else {
                ... filter value here ...
            }
      }];
}
bbum
  • 162,346
  • 23
  • 271
  • 359
5

In the simplest form:

[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
    if ([obj isKindOfClass:[NSNull class]]) [dictionary setValue:[NSString stringWithString:@""] forKey:key];
} ];
jbcaveman
  • 911
  • 1
  • 10
  • 19
2

You could use a recursive method, like this:

- (void)recursive:(NSDictionary*)aDictionary {

    for (id key in aDictionary) {

        id value = [aDictionary objectForKey:key];

        if ([value isKindOfClass:[NSDictionary class]]) {
            [self recursive:value];
        } else {
            // Do something else, the value is not a dictionary
        }
    }

}
bbum
  • 162,346
  • 23
  • 271
  • 359
thijsai
  • 1,795
  • 1
  • 18
  • 26
  • Just curious aren't you forgetting * after NSDictionary? I am having a compiler error. btw really nice process. – topgun Dec 12 '11 at 17:58
0

Inside your loop as you are checking for values use this for checking against null.

if ([[dict objectForKey:@"Gender"] isKindOfClass:[NSNull class]]) {
   // null value
   myGender = @"";
}
Bill Burgess
  • 14,054
  • 6
  • 49
  • 86
0
- (void)recursive:(NSDictionary)dictionary {

    for (NSString *key in [dictionary allKeys]) {

        id nullString = [dictionary objectForKey:key];

        if ([nullString isKindOfClass:[NSDictionary class]]) {
            [self recursive:(NSDictionary*)nullString];
        } else {
            if ( (NSString*)nullString == nil)
                [dictionary setObject:@"" forKey:@"key"];
        }
    }

}
Ali3n
  • 1,244
  • 6
  • 10
  • 1
    This isn't going to work because you are comparing against `nil`. You can't store `nil` in a dictionary. If there are null values in the dictionary, they will be the `[NSNull null]` singleton. – Jim Dec 12 '11 at 17:43
  • Jim, cant you look for isKindOfClass:[NSNull class] here than for == nil? – topgun Dec 12 '11 at 17:59
  • 1
    @kforkarim That is what Jim is saying; but you don't need to check for `isKindOfClass:[NSNull null]` as there is only one singleton. Use `isEqual:` to be technically correct. Also, that code won't compile; `NSDictionary` is not mutable and `(NSDictionary)` is invalid. – bbum Dec 12 '11 at 18:12