OS X (Mac 10.8.2) では、電話番号をオブジェクトABPerson
の配列として返すカテゴリを追加しました。オブジェクトには と の 2 つのプロパティがPhone
あります。すべての電話番号を取得し、それらをフィルタリングして、入力に一致するものだけを含めたいと考えています。Phone
label
value
label
valueForKey:
s の配列全体、またはキーと ABPerson
を持つ個々の人に対してネストされた呼び出しを使用すると、目的の結果が得られます。ただし、s を単一に連結すると、配列全体を検索するときに適切な結果が得られますが、単一の人物オブジェクトを評価するときは得られません。@"phones"
@"label"
valueForKey:
valueForKeyPath:
#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
たり、望ましい結果を返す people 配列をフィルタリングするための述語を提供したりできる場合は、非常に感謝しています。