在 OS X (Mac 10.8.2) 中,我添加了一个类别以ABPerson
将电话号码作为对象数组返回Phone
。该Phone
对象有两个属性,label
和value
。我想获取所有电话号码并过滤它们以仅包含label
与输入匹配的电话号码。
valueForKey:
如果我在整个ABPerson
s 数组或带有键的个人上使用嵌套调用@"phones"
and @"label"
,那么我会得到所需的结果。但是,如果我将valueForKey:
s 连接到单个valueForKeyPath:
,那么在搜索整个数组时我仍然会得到正确的结果,但在评估单个 person 对象时不会:
#import <Cocoa/Cocoa.h>
#import <AddressBook/AddressBook.h>
@interface Phone : NSObject
@property (retain) NSString *label;
@property (retain) NSString *value;
@end
@implementation Phone
- (void)dealloc {
self.label = nil;
self.value = nil;
[super dealloc];
}
@end
@interface ABPerson (phones)
- (NSArray *)phones;
@end
@implementation ABPerson (phones)
- (NSArray *)phones {
NSMutableArray *phones = [NSMutableArray array];
ABMultiValue *values = [self valueForProperty:kABPhoneProperty];
for (NSInteger i = 0; i < [values count]; i++) {
Phone *phone = [[Phone alloc] init];
phone.label = ABLocalizedPropertyOrLabel([values labelAtIndex:i]);
phone.value = [values valueAtIndex:i];
[phones addObject:phone];
[phone release];
}
return [NSArray arrayWithArray:phones];
}
@end
int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *people = [[ABAddressBook sharedAddressBook] people];
ABPerson *person = [people objectAtIndex:0];
NSArray *a0 = [[people valueForKey:@"phones"] valueForKey:@"label"];
NSArray *a1 = [people valueForKeyPath:@"phones.label"];
NSLog(@"a0 == a1: %d", [a0 isEqualTo:a1]);
NSArray *a2 = [[person valueForKey:@"phones"] valueForKey:@"label"];
NSArray *a3 = [person valueForKeyPath:@"phones.label"];
NSLog(@"a2 == a3: %d", [a2 isEqualTo:a3]);
NSLog(@"people count : %3ld", [people count]);
NSLog(@"people phones label count (valueForKey.valueForKey): %3ld", [a0 count]);
NSLog(@"people phones label count (valueForKeyPath): %3ld", [a1 count]);
NSLog(@"person phones label count (valueForKey.valueForKey): %3ld", [a2 count]);
NSLog(@"person phones label count (valueForKeyPath): %3ld", [a3 count]);
NSLog(@"----------------------------------------------------------");
NSLog(@"people phones label objectAtIndex:0 (valueForKeyPath): %@", [a1 objectAtIndex:0]);
NSLog(@"person phones label (valueForKey.valueForKey): %@", a2);
NSLog(@"person phones label (valueForKeyPath): %@", a3);
[pool release];
return 0;
}
这输出:
2013-01-07 15:03:42.537 test[51919:303] a0 == a1: 1
2013-01-07 15:03:42.540 test[51919:303] a2 == a3: 0
2013-01-07 15:03:42.541 test[51919:303] people count : 200
2013-01-07 15:03:42.543 test[51919:303] people phones label count (valueForKey.valueForKey): 200
2013-01-07 15:03:42.544 test[51919:303] people phones label count (valueForKeyPath): 200
2013-01-07 15:03:42.545 test[51919:303] person phones label count (valueForKey.valueForKey): 2
2013-01-07 15:03:42.546 test[51919:303] person phones label count (valueForKeyPath): 0
2013-01-07 15:03:42.547 test[51919:303] ----------------------------------------------------------
2013-01-07 15:03:42.548 test[51919:303] people phones label objectAtIndex:0 (valueForKeyPath): (
mobile,
home
)
2013-01-07 15:03:42.549 test[51919:303] person phones label (valueForKey.valueForKey): (
mobile,
home
)
2013-01-07 15:03:42.551 test[51919:303] person phones label (valueForKeyPath): (null)
为什么不[[person valueForKey:@"phones"] valueForKey:@"label"]
等于[person valueForKeyPath:@"phones.label"]
?这很重要,因为我想使用完整的@"phone.label"
密钥路径对所有联系人使用谓词过滤器,如下所示:
NSString *value = @"home";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY phones.label == %@", value];
NSArray *a4 = [people filteredArrayUsingPredicate:predicate];
在此示例中,a4
始终为空(使用不带“ANY”标志的谓词仍会导致过滤后的数组为空)。我相信这是因为filteredArrayUsingPredicate:
本质上是在评估每个对象(人),valueForKeyPath:
并且如上所述,这不适用于单个人对象。它是否正确?
如果有人可以阐明对象失败valueForKeyPath:
的原因ABPerson
,或者提供一个谓词来过滤返回所需结果的人员数组,我将不胜感激。