3

I'm trying to flatten a two dimensional array of dictionaries with the use of KVC.

NSArray *toBeFlatten = @[@[@{@1:@1}],@[@{@2:@2}]];
NSArray *flat = [toBeFlatten valueForKeyPath:@"@unionOfArrays.self"];
// flat:@[NSNull.null, NSNull.null];

Why are the dictionaries "converted" to NSNull?

melbic
  • 11,988
  • 5
  • 33
  • 37

1 Answers1

5

It's because valueForKeyPath: also applies to the dictionaries. And how does it work? It looks in each dictionary, tries to use "self" as a key, finds no such key, and returns NSNull to represent the missing value.

To see what I mean, consider this variation on your example:

NSArray *toBeFlatten = @[@[@{@"self":@"hey"}],@[@{@"other":@"ho"}]];
NSArray *flat = [toBeFlatten valueForKeyPath:@"@unionOfArrays.self"];

The result is @[@"hey", NSNull.null] — the value "hey" for the matching key "self" in the first dictionary, and the null because no key matched in the second dictionary.

What you probably meant to say is valueForKeyPath:@"@unionOfArrays.@self" (notice the at-sign, making self an operator, not a key).

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • On the whole, however, I would find this use of `self` rather scary, as it is undocumented AFAIK. – matt Jan 24 '17 at 17:28
  • Didn't think that far, but that makes perfect sense. So there are actually some wrong answers floating around. Like this one: http://stackoverflow.com/a/17091443/270265 – melbic Jan 24 '17 at 19:35
  • @melbic I don't think you have quite appreciated what my answer says. The "wrong answer" you pointed to is not wrong, because the innermost objects are not _dictionaries_. KVC has different rules for what a key path means when we reach a dictionary than for what it means when we reach some other type of object. Your original code would have worked if these had been arrays of arrays of NSNumbers, for example. – matt Jan 24 '17 at 20:27
  • 2
    @matt Which use of `self` is undocumented? The documentation of `-[NSDictionary valueForKey:]` says "If key does not start with “@”, invokes objectForKey:. If key does start with “@”, strips the “@” and invokes [super valueForKey:] with the rest of the key.". KVC turns key `self` into method `self`. – Willeke Jan 24 '17 at 22:57
  • @Willeke Brilliant, thank you! So should I edit my answer to say that `@self` is the `self` method (rather than saying "operator")? – matt Jan 24 '17 at 22:57
  • @matt Of course I do understand your answer. What I meant, was that it is potentially dangerous, because it isn't a general solution working for all NSObjects. – melbic Jan 25 '17 at 08:33