Операторы коллекции KVC для примитивных значений

Можно ли использовать операторы коллекции для примитивных значений?

У меня есть объект с примитивным свойством duration.

@property (nonatomic) NSTimeInterval duration;

У меня есть NSArray указанных объектов, и я хотел бы использовать операцию сбора массива, чтобы получить сумму длительности. Проблема в том, что @"@sum.duration" вместо этого ожидает NSNumber.

Придется ли мне делать это по старинке, или есть способ использовать примитивы?


person RileyE    schedule 04.12.2013    source источник


Ответы (2)


Из "Скалярная и структурная поддержка" в "Руководстве по программированию ключ-значение":

Кодирование "ключ-значение" обеспечивает поддержку скалярных значений и структур данных путем автоматического переноса и развертывания значений экземпляров NSNumber и NSValue.

So

NSNumber *sum = [array valueForKeyPath:@"@sum.duration"];

просто работает, даже если duration является скалярным свойством. Небольшой автономный пример:

#import <Foundation/Foundation.h>

@interface MyClass : NSObject
@property(nonatomic, assign) NSTimeInterval duration;
@end

@implementation MyClass
@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        MyClass *obj1 = [MyClass new];
        obj1.duration = 123.4;
        MyClass *obj2 = [MyClass new];
        obj2.duration = 456.7;
        NSArray *array = @[obj1, obj2];

        NSNumber *sum = [array valueForKeyPath:@"@sum.duration"];
        NSLog(@"sum = %@", sum);
    }
    return 0;
}

Выход: 580,1.

person Martin R    schedule 04.12.2013
comment
Интересный. Интересно, почему я получил эту ошибку: Exception: [<__NSArrayM 0xe733040> valueForUndefinedKey:]: this class is not key value coding-compliant for the key sum.duration. - person RileyE; 04.12.2013
comment
@RileyE: я проверил это, прежде чем публиковать ответ. Вы написали @sum.duration или sum.duration? - person Martin R; 04.12.2013
comment
@RileyE: я добавил в свой ответ рабочий пример. - person Martin R; 04.12.2013
comment
@RileyE, ты пытаешься использовать valueForKey, а не valueForKeyPath:? - person Rob Napier; 04.12.2013
comment
@RobNapier Хороший улов! Я уходил этот пост по какой-то странной причине вместо документацию. - person RileyE; 04.12.2013
comment
Приносим извинения за доставленные неудобства, Мартин! И благодарю вас! - person RileyE; 04.12.2013

Вы всегда можете добавить другое свойство:

@property (nonatomic) NSNumber *durationNumber;

и реализовать как геттер, так и сеттер:

- (NSNumber *)durationNumber {
    return [NSNumber numberWithDouble:self.duration];
}

- (void)setDurationNumber:(NSNumber *)durationNumber {
    self.duration = durationNumber.doubleValue;
}

Реализация как сеттера, так и геттера запрещает автоматический синтез резервного ivar.

person godel9    schedule 04.12.2013
comment
Ага. Я думал об этом, но делать это по старинке кажется более оптимальным способом. Быстрый итератор цикла for, который запускается один раз и не требует выделения NSNumber. Тем не менее, спасибо за ответ! - person RileyE; 04.12.2013