返回
CoreData请求(Fetch Request)断言(NSPredicate)使用误区
IOS
2023-12-05 21:00:19
面面俱到?
NSPredicate * predicate = [NSPredicate predicateWithBlock:^BOOL(User *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.status.integerValue == UserStatusActive;
}];
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"User"];
request.predicate = predicate;
这段代码中,谓词中的evaluatedObject.status.integerValue == UserStatusActive
这样的判断是错误的。status
是NSNumber
类型,而UserStatusActive
却是NSInteger
。显然这是一个隐式类型转换,这在CoreData中不是一个好主意。
正确姿势:
NSPredicate * predicate = [NSPredicate predicateWithBlock:^BOOL(User *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.status == [NSNumber numberWithInteger:UserStatusActive];
}];
nil is nil
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(User *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.name.length;
}];
length
属性返回NSUInteger
类型,这表示不可能为nil 。但谓词会返回NO
,而不是你期望的YES
。这是因为nil
对象没有length
属性,导致谓词条件永远不会满足。
正确姿势:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(User *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.name != nil && evaluatedObject.name.length;
}];
BOOL类型比较
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(User *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.active.boolValue == YES;
}];
active
属性类型是BOOL
,而YES
却是NSInteger
。编译器不会通过上面的代码。
正确姿势:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(User *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.active.boolValue;
}];
类型转换
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(User *evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject.status integerValue] < 5;
}];
同上,status
是NSNumber
类型,而[evaluatedObject.status integerValue]
却是NSInteger
,也是一个隐式类型转换。
正确姿势:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(User *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.status.integerValue < 5;
}];
使用KVC
NSPredicate * predicate = [NSPredicate predicateWithBlock:^BOOL(User *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.status.integerValue == [[NSUserDefaults standardUserDefaults] integerForKey:@"UserStatusActive"];
}];
看起来似乎没有什么问题,但实际上会出乎意料。这是因为KVC会对UserStatusActive
键进行类型转换,返回一个NSNumber
对象。
正确姿势:
NSInteger status = [[NSUserDefaults standardUserDefaults] integerForKey:@"UserStatusActive"];
NSPredicate * predicate = [NSPredicate predicateWithBlock:^BOOL(User *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.status.integerValue == status;
}];
总结
使用断言(NSPredicate)时需要注意以下几点:
- 避免隐式类型转换
- 确保nil对象不会导致谓词失败
- BOOL类型的比较直接使用
boolValue
属性 - 类型转换时明确指定转换类型
- 使用KVC时注意类型转换
遵循这些准则,可以避免使用断言(NSPredicate)时的常见错误,并确保您的CoreData查询按预期工作。