Арифметические операторы и кодирование ключ-значение

Можно ли выполнять арифметику с использованием кодирования значения ключа Obj-C? Я ищу что-то вроде этого:

[obj valueForKeyPath:@"(val1+val2)"]

или вам нужно реализовать свойство, которое добавляет два значения вручную?


person Trenskow    schedule 21.01.2013    source источник
comment
Какова ваша точная потребность?   -  person Anoop Vaidya    schedule 21.01.2013
comment
Я так не думаю, приятель. Я думаю, что это строковая переменная, которую вы даете, и она будет сохранена. Я думаю, что к настоящему времени вы могли бы попробовать все сами.   -  person Prajwal Udupa    schedule 21.01.2013


Ответы (2)


Арифметика с использованием KVC невозможна.

Вы можете выполнять арифметические действия со строками, а затем передавать их [obj valueforKeyPath:...] как:

NSString *val1=@"3";
NSString *val2=@"5";

NSString *formula = [NSString stringWithFormat:@"%@+%@",val1,val2];

NSExpression *exp = [NSExpression expressionWithFormat:formula];
NSNumber *resultForCustomFormula = [exp expressionValueWithObject:nil context:nil];

NSLog(@"%f", [resultForCustomFormula floatValue]);
person Anoop Vaidya    schedule 21.01.2013
comment
Большое спасибо! Я посмотрю на NSExpression и посмотрю, что я могу с ним сделать. - person Trenskow; 21.01.2013

Я использовал пример NSExpression, предоставленный AKV, для создания этой категории NSObject.

Это расширяет значениеForKeyPath: поэтому он поддерживает такие выражения:

[obj valueForKeyPath:@"(val1+val2)"];

или на примере:

[obj valueForKeyPath:@"@min.(val1+val2)"];

Категория

#import <objc/runtime.h>

@implementation NSObject (KVCExtension)

#pragma mark - Initializing a Class

+ (void)load {

    SEL valueForKeyPath = @selector(valueForKeyPath:);
    SEL extendedValueForKeyPath = @selector(extendedValueForKeyPath:);
    Method valueForKeyPathMethod = class_getInstanceMethod([self class], valueForKeyPath);
    Method extendedValueForKeyPathMethod = class_getInstanceMethod([self class], extendedValueForKeyPath);
    method_exchangeImplementations(valueForKeyPathMethod, extendedValueForKeyPathMethod);

}

#pragma mark - Key-Value Coding

- (id)extendedValueForKeyPath:(NSString *)keyPath {

    /* NOTICE: +load exchanged this method with valueForKey: !!!
     Thus calling extendedValueForKeyPath: now means we're calling the old valueForKeyPath: method and vice versa.
    */

    if ([keyPath length] > 0 && [keyPath characterAtIndex:0] == '(') {

        if ([self isKindOfClass:[NSArray class]]) {

            NSMutableArray *results = [[NSMutableArray alloc] init];
            for (id obj in (NSArray *)self)
                [results addObject:[obj valueForKeyPath:keyPath]];
            return [results copy];

        } else {

            NSRegularExpression *regExp = [NSRegularExpression regularExpressionWithPattern:@"[A-Za-z0-9_\\.]*"
                                                                    options:0
                                                                                  error:nil];

            NSMutableString *mKeyPath = [keyPath mutableCopy];

            [regExp enumerateMatchesInString:mKeyPath options:0 range:NSMakeRange(0, [keyPath length]) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {

                NSRange range = [[result resultByAdjustingRangesWithOffset:[mKeyPath length] - [keyPath length]] range];
                if (range.length > 0) {

                    NSString *key = [mKeyPath substringWithRange:range];
                    NSString *val = [[self extendedValueForKeyPath:key] stringValue];

                    [mKeyPath replaceCharactersInRange:range withString:val];

                }

            }];

            NSExpression *expression = [NSExpression expressionWithFormat:mKeyPath];
            return [expression expressionValueWithObject:nil context:nil];

        }

    } else
        return [self extendedValueForKeyPath:keyPath];

}

@end
person Trenskow    schedule 21.01.2013