5

I recently read some documentation and some blog entries about Key-Value Coding and found it extremely useful. I want to utilize it for my case, but I haven't been successful so far.

In my case, I have an NSMutableArray containing CGPoint's transformed to NSValue's. I will be adding many points to this data array and I want to get the minimum/maximum x and y values. For example:

NSMutableArray *data = [[NSMutableArray alloc] init];
[data addObject:[NSValue valueWithCGPoint:CGPointMake(20.0f, 10.0f)]];
[data addObject:[NSValue valueWithCGPoint:CGPointMake(5.0f, -15.0f)]];
[data addObject:[NSValue valueWithCGPoint:CGPointMake(-5.0f, 20.0f)]];
[data addObject:[NSValue valueWithCGPoint:CGPointMake(15.0f, 30.0f)]];

// min X:  -5.0,  max X: 20.0
// min Y: -15.0,  max Y: 30.0

I have two approaches so far. The first one is to store these four values in class instance variables and when a new object is added, compare it with those variables and update them if necessary. The second one involves a for-loop to to find the extremum values, however this approach would be inefficient.

If possible, I would like to use KVC to do this task and I believe that it would be a more general solution than those I have. In the future, I might also need to remove some of the objects from the array and that would make my first approach inapplicable and all I am left with would be the for-loop.

I tried to use some key paths, i.e. @"@max.x", @"@max.position.x" but all I got is an NSUnknownKeyException.

4

2 回答 2

9

如果您使用类别来告诉如何访问 a 的和值,则可以使其工作:NSValuexyCGPoint

@interface NSValue (MyKeyCategory)
- (id)valueForKey:(NSString *)key;
@end

@implementation NSValue (MyKeyCategory)
- (id)valueForKey:(NSString *)key
{
    if (strcmp([self objCType], @encode(CGPoint)) == 0) {
        CGPoint p = [self CGPointValue];
        if ([key isEqualToString:@"x"]) {
            return @(p.x);
        } else if ([key isEqualToString:@"y"]) {
            return @(p.y);
        }
    }
    return [super valueForKey:key];
}
@end

然后

CGFloat maxx = [[yourArray valueForKeyPath:@"@max.x"] floatValue];

确实有效。但请注意,一个简单的循环会快得多,特别是如果您必须计算所有 4 个值@max.x@max.y@min.x@min.y

于 2013-05-28T10:05:15.297 回答
1

这在您当前的方法中是不可能的。ACGPoint不是 obj-c 对象,因此您无法通过 KVC 探索它的值。NSValue仅将CGPoint其视为二进制数据,不了解数据的内部结构。编译后甚至无法访问名称x和字段yCGPoint

CGPoint( KVC 可以访问值的唯一例外是CAAnimation覆盖键值CALayer搜索)。

可能最好的解决方案是自己实现它,请注意,您可以做一些巧妙的缓存 - 添加点时测试当前最大/最小值,并在删除当前最小值/最大值时清除最小值/最大值。

于 2013-05-28T09:22:37.393 回答