算术运算符和键值编码
是否可以使用Obj-C键值编码进行算术运算? 我正在寻找这样的东西:
[obj valueForKeyPath:@"(val1+val2)"]
或者你必须实现一个手动添加两个值的属性?
使用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]);
我使用了AKV给出的NSExpression示例来创建这个NSObject类别。
这扩展了valueForKeyPath:所以它支持这样的表达式:
[obj valueForKeyPath:@"(val1+val2)"];
或者每个例子:
[obj valueForKeyPath:@"@min.(val1+val2)"];
类别
#import @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