KVC strange behavior
Asked Answered
G

2

2

Why this code works fine:

NSArray* arr = @[[CALayer layer], [CALayer layer]];
NSString *sumKeyPath = @"@sum.bounds.size.width";
CGFloat totalSize = [[arr valueForKeyPath:sumKeyPath] floatValue];

But this code give error:

NSArray* arr = @[[UIImage imageNamed:@"img1"], [UIImage imageNamed:@"img2"]];
NSString *sumKeyPath = @"@sum.size.width";
CGFloat totalSize = [[arr valueForKeyPath:sumKeyPath] floatValue];

Error: [NSConcreteValue valueForUndefinedKey:]: this class is not key value coding-compliant for the key width.

NSArray* arr = @[[UIView new], [UIView new]];
NSString *sumKeyPath = @"@sum.bounds.size.width";
CGFloat totalSize = [[arr valueForKeyPath:sumKeyPath] floatValue];

give the same error

Gamin answered 27/3, 2013 at 10:56 Comment(0)
R
8

CALayer has a special implementation for valueForKeyPath:. For example, the following works:

CALayer *layer = [CALayer layer];
id x0 = [layer valueForKeyPath:@"bounds"];
// --> NSValue object containing a NSRect
id y0 = [layer valueForKeyPath:@"bounds.size"];
// --> NSValue object containing a NSSize
id z0 = [layer valueForKeyPath:@"bounds.size.width"];
// --> NSNumber object containing a float

But the following does not work:

CALayer *layer = [CALayer layer];
id x = [layer valueForKey:@"bounds"];
// --> NSValue object containing a NSRect
id y = [x valueForKey:@"size"];
// --> Exception: '[<NSConcreteValue 0x71189e0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key size.'

So generally, NSValue objects containing a NSRect or NSSize are not key-value compliant. It works only with CALayer because the valueForKeyPath: implementation handles the entire key path, instead of evaluating the first key and passing down the remaining key path.

UIImage does not have a special implementation for valueForKeyPath:. Therefore

UIImage *img1 = [UIImage imageNamed:@"img1"];
id x1 = [img1 valueForKey:@"size"];
// --> NSValue containing a NSSize

works, but

UIImage *img1 = [UIImage imageNamed:@"img1"];
id x1 = [img1 valueForKeyPath:@"size.width"];

does not work.

Retail answered 27/3, 2013 at 11:41 Comment(0)
R
2

I think the error tells you exactly what that problem is! "this class is not key value coding-compliant for the key width."

Rescission answered 27/3, 2013 at 11:6 Comment(2)
What difference? bounds- not NSObject, size- not NSObject. Why first code works fine? Size in first case have same type and in the second case.Gamin
See @martin's answer. CALayer does clever stuff in valueForKeyPath: (sometimes).Rescission

© 2022 - 2024 — McMap. All rights reserved.