我必须将数据从以前的应用程序版本迁移到新版本.这也会影响用户保存的一些谓词(NSPredicate实例),这意味着我必须以编程方式更改它们.
目前我尝试用[NSPredicate predicateFormat]解析我得到的字符串并手动更改一些表达式.例如oldKeyPath ==“something”to newKeyPath ==“something”.但感觉就像一个黑客,我很好奇,如果有更好的方法?
我阅读了Apple关于使用NSPredicate和NSExpression进行编程的文档.有很多方法可以从NSExpressions中组合NSPredicate对象.我希望找到从NSPredicate获取NSExpression对象的相反方法.我错过了什么吗?
谢谢你的提示.
解
感谢Martin R,我能够在NSPredicate上创建一个类别,允许我对表达式进行修改.
@implementation NSPredicate (ExtractComparisions)
- (NSPredicate *)predicateByChangingComparisionsWithBlock:(NSPredicate *(^)(NSComparisonPredicate *))block {
if ([self isKindOfClass: [NSCompoundPredicate class]]) {
NSCompoundPredicate *compPred = (NSCompoundPredicate *)self;
NSMutableArray *predicates = [NSMutableArray array];
for (NSPredicate *predicate in [compPred subpredicates]) {
NSPredicate *newPredicate = [predicate predicateByChangingComparisionsWithBlock: block];
if (newPredicate != nil)
[predicates addObject: newPredicate];
}
return [[[NSCompoundPredicate alloc] initWithType: compPred.compoundPredicateType
subpredicates: predicates] autorelease];
} if ([self isKindOfClass: [NSComparisonPredicate class]]) {
return block((NSComparisonPredicate *)self);
}
return self;
}
@end
以下是有关如何使用它的示例代码
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"key.path like %@ and count > 17", @"Hello"];
NSPredicate *newPredicate = [predicate predicateByChangingComparisionsWithBlock:
^NSPredicate *(NSComparisonPredicate *cp) {
NSExpression *left = [cp leftExpression];
NSExpression *right = [cp rightExpression];
if ([[cp leftExpression] expressionType] == NSKeyPathExpressionType) {
NSString *keyPath = [[cp leftExpression] keyPath];
if ([keyPath isEqualToString: @"key.path"])
left = [NSExpression expressionForKeyPath: @"key.new.path"];
return [NSComparisonPredicate predicateWithLeftExpression: left
rightExpression: right
modifier: cp.comparisonPredicateModifier
type: cp.predicateOperatorType
options:cp.options];
}
return cp;
}];
NSLog(@"Before: %@", predicate);
NSLog(@"After: %@", newPredicate);
}
最佳答案 (这只是一个想法.)每个谓词都是子类的实例
NSCompoundPredicate或NSComparisonPredicate.所以你可以查看实际情况
谓词的类,将其强制转换为该类的对象然后
检查其属性.如有必要,请使用子谓词或重复该过程
表达式.
以下只是一个简单的复合谓词如何的例子
以这种方式“解剖”.检查所有案例不是一般解决方案,
但可能会指出你正确的方向.
NSPredicate *p0 = [NSPredicate predicateWithFormat:@"foo = 'bar' AND count > 17"];
if ([p0 isKindOfClass:[NSCompoundPredicate class]]) {
NSCompoundPredicate *p0a = (NSCompoundPredicate *)p0;
NSCompoundPredicateType type0 = p0a.compoundPredicateType; // NSAndPredicateType
NSPredicate *p1 = p0a.subpredicates[0]; // foo = 'bar'
NSPredicate *p2 = p0a.subpredicates[1]; // count > 17
if ([p1 isKindOfClass:[NSComparisonPredicate class]]) {
NSComparisonPredicate *p1a = (NSComparisonPredicate *)p1;
NSPredicateOperatorType type1 = p1a.predicateOperatorType; // NSEqualToPredicateOperatorType
NSExpression *e3 = p1a.leftExpression; // foo, NSKeyPathExpression
NSExpression *e4 = p1a.rightExpression; // "bar", NSConstantValueExpression
}
if ([p2 isKindOfClass:[NSComparisonPredicate class]]) {
NSComparisonPredicate *p2a = (NSComparisonPredicate *)p2;
NSPredicateOperatorType type2 = p2a.predicateOperatorType; // NSGreaterThanPredicateOperatorType
NSExpression *e5 = p2a.leftExpression; // count, NSKeyPathExpression
NSExpression *e6 = p2a.rightExpression; // 17, NSConstantValueExpression
}
}