[背景:iOS 7,Xcode 5,两者都是截至2014年2月的最新版本.测试数据是在iPhone 5(真实设备,非模拟器)上除了基本联系信息之外还有多个电话号码和多个地址的地址簿条目]
我的目标是使用AddressBookUI方法允许用户指定联系人,然后使用各种字段(地址,电话号码等)填充我的代码中的GUI.这ABPeoplePickerNavigationController是允许用户按名称选择联系人的标准机制.这样做会导致调用此委托方法:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
Run Code Online (Sandbox Code Playgroud)
但是,如果我此时检查人员记录,则没有任何多值字段具有任何数据.所以我提取了RecordID,检索到了,结果ABRecordRef也没有填充多值字段.
如果我YES从委托方法返回,则会向用户显示另一个显示联系人详细信息的UI.触摸任何字段都会导致此委托方法调用
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
Run Code Online (Sandbox Code Playgroud)
并且ABRecordRef填写了所有多值字段.
我找不到有关延迟加载的记录的任何信息,或者存在所需的延迟或权限问题,这会阻止字段被填充.而我用来检查记录的代码是一种方法,所以在第二个实例中找到值的完全相同的代码无法在第一个实例中找到它.
有关可能发生的事情的任何建议,或者如何在不向用户显示第二个UI的情况下检索完整记录?
我正在使用Apple的QuickContacts示例代码.以下是我所做的补充和更改.
+(NSMutableDictionary *)convertABRecordRef:(ABRecordRef)person
{
// Initialize a mutable dictionary and give it initial values.
NSMutableDictionary *contactInfoDict = [[NSMutableDictionary alloc] initWithCapacity:12];
// Use a general Core Foundation object.
CFTypeRef generalCFObject = ABRecordCopyValue(person, kABPersonFirstNameProperty);
ABRecordID foundId = ABRecordGetRecordID(person);
NSNumber *personIDNum = [NSNumber numberWithInteger:foundId];
[contactInfoDict setObject:personIDNum forKey:@"recordID"];
// Get the first name.
if (generalCFObject)
{
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:@"firstName"];
CFRelease(generalCFObject);
}
// Get the last name.
generalCFObject = ABRecordCopyValue(person, kABPersonLastNameProperty);
if (generalCFObject) {
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:@"lastName"];
CFRelease(generalCFObject);
}
generalCFObject = ABRecordCopyValue(person, kABPersonOrganizationProperty);
if (generalCFObject) {
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:@"companyName"];
CFRelease(generalCFObject);
}
//ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
//NSArray *numbers = (NSArray *)ABMultiValueCopyArrayOfAllValues(phones);
// Get the phone numbers as a multi-value property.
ABMultiValueRef phonesRef = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex phoneCount = ABMultiValueGetCount(phonesRef);
for (CFIndex i=0; i<ABMultiValueGetCount(phonesRef); i++) {
CFStringRef currentPhoneLabel = ABMultiValueCopyLabelAtIndex(phonesRef, i);
CFStringRef currentPhoneValue = ABMultiValueCopyValueAtIndex(phonesRef, i);
if (CFStringCompare(currentPhoneLabel, kABPersonPhoneMobileLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *)currentPhoneValue forKey:@"mobileNumber"];
}
if (CFStringCompare(currentPhoneLabel, kABHomeLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *)currentPhoneValue forKey:@"homeNumber"];
}
if (CFStringCompare(currentPhoneLabel, kABWorkLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *)currentPhoneValue forKey:@"workNumber"];
}
CFRelease(currentPhoneLabel);
CFRelease(currentPhoneValue);
}
CFRelease(phonesRef);
// Get the e-mail addresses as a multi-value property.
ABMultiValueRef emailsRef = ABRecordCopyValue(person, kABPersonEmailProperty);
for (int i=0; i<ABMultiValueGetCount(emailsRef); i++)
{
CFStringRef currentEmailLabel = ABMultiValueCopyLabelAtIndex(emailsRef, i);
CFStringRef currentEmailValue = ABMultiValueCopyValueAtIndex(emailsRef, i);
if (CFStringCompare(currentEmailLabel, kABHomeLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *)currentEmailValue forKey:@"homeEmail"];
}
if (CFStringCompare(currentEmailLabel, kABWorkLabel, 0) == kCFCompareEqualTo) {
[contactInfoDict setObject:(__bridge NSString *)currentEmailValue forKey:@"workEmail"];
}
CFRelease(currentEmailLabel);
CFRelease(currentEmailValue);
}
CFRelease(emailsRef);
// Get the first street address among all addresses of the selected contact.
ABMultiValueRef addressRef = ABRecordCopyValue(person, kABPersonAddressProperty);
if (ABMultiValueGetCount(addressRef) > 0)
{
CFIndex numberOfAddresses = ABMultiValueGetCount(addressRef);
for (CFIndex i=0; i<numberOfAddresses; i++)
{
CFStringRef label = ABMultiValueCopyLabelAtIndex(addressRef, i);
if (label)
{
if (CFEqual(label, kABHomeLabel))
{
NSDictionary *addressDict = (__bridge NSDictionary *)ABMultiValueCopyValueAtIndex(addressRef, 0);
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressStreetKey] forKey:@"homeAddress"];
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressZIPKey] forKey:@"homeZipCode"];
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressCityKey] forKey:@"homeCity"];
}
else if (CFEqual(label, kABWorkLabel))
{
NSDictionary *addressDict = (__bridge NSDictionary *)ABMultiValueCopyValueAtIndex(addressRef, 0);
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressStreetKey] forKey:@"workAddress"];
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressZIPKey] forKey:@"workZipCode"];
[contactInfoDict setObject:[addressDict objectForKey:(NSString *)kABPersonAddressCityKey] forKey:@"workCity"];
}
CFRelease(label);
}
}
}
CFRelease(addressRef);
// If the contact has an image then get it too.
if (ABPersonHasImageData(person)) {
NSData *contactImageData = (__bridge NSData *)ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail);
[contactInfoDict setObject:contactImageData forKey:@"image"];
}
return contactInfoDict;
}
// Displays the information of a selected person
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
// only returns a few fields, and none of the multi value ones :-(
NSMutableDictionary *results = [QuickContactsViewController convertABRecordRef:person];
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
ABRecordID foundId = ABRecordGetRecordID(person);
ABRecordRef fullPerson = ABAddressBookGetPersonWithRecordID(addressBook, foundId);
// also only returns a few fields!?
NSMutableDictionary *selectedFromID = [QuickContactsViewController convertABRecordRef:fullPerson];
return YES;
}
// Does not allow users to perform default actions such as dialing a phone number, when they select a person property.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
// returns all simple and multi-value fields!?
NSMutableDictionary *results = [QuickContactsViewController convertABRecordRef:person];
return NO;
}
Run Code Online (Sandbox Code Playgroud)
编辑:添加我的解决方案(感谢Thorsten!).
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
NSArray *allPersonRecords = (NSArray *)CFBridgingRelease(ABPersonCopyArrayOfAllLinkedPeople(person));
NSLog(@"Count Linked People: %i", allPersonRecords.count);
NSMutableDictionary *results = [[NSMutableDictionary alloc]initWithCapacity:12];
for (int x=0; x<[allPersonRecords count]; x++)
{
ABRecordRef user = CFBridgingRetain([allPersonRecords objectAtIndex:x]);
NSMutableDictionary *userFromArray = [QuickContactsViewController convertABRecordRef:user];
[results addEntriesFromDictionary:userFromArray]; // mush them together
CFRelease(user);
}
NSLog(@"finished! Total number of contact fields found:%d", [results count]);
// do something with the data here...
return NO;
}
Run Code Online (Sandbox Code Playgroud)
一个人可以由多人组成。迭代所有人以获取您的数据:
NSArray *people = (NSArray *)CFBridgingRelease(ABPersonCopyArrayOfAllLinkedPeople(person));
...
ABRecordRef user = CFBridgingRetain([people objectAtIndex:i]);
...
valuesRef = ABRecordCopyValue(user, kABPersonPhoneProperty);
valuesCount = 0;
if (valuesRef != nil) valuesCount = ABMultiValueGetCount(valuesRef);
...
Run Code Online (Sandbox Code Playgroud)
华泰
| 归档时间: |
|
| 查看次数: |
537 次 |
| 最近记录: |