Поля ABRecordRef не заполнены?
[фон: iOS 7, Xcode 5, оба обновленные по состоянию на февраль 2014 года. Тестовые данные - это записи адресной книги с несколькими телефонными номерами и несколькими адресами в дополнение к основной контактной информации на iPhone 5 (реальное устройство, а не симулятор)]
Моя цель - использовать методы AddressBookUI, чтобы пользователь мог указать контакт, а затем использовать различные поля (адреса, номера телефонов и т. Д.), Чтобы заполнить GUI в моем коде. ABPeoplePickerNavigationController
это стандартный механизм, позволяющий пользователю выбрать контакт по имени. В результате этого вызывается метод делегата:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
Однако, если я проверю запись о человеке на этом этапе, ни одно из полей с несколькими значениями не содержит данных. Итак, я извлек RecordID
, извлек это, и в результате ABRecordRef
также не имеет заполненных полей с несколькими значениями.
Если я вернусь YES
из метода делегата пользователю отображается другой пользовательский интерфейс с отображаемой контактной информацией. Прикосновение к любому полю приводит к вызову метода делегата
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
и это ABRecordRef
заполнены все поля с несколькими значениями
Я не могу найти какую-либо информацию о лениво загружаемых записях, или о наличии требуемой задержки, или о проблеме с разрешениями, которая не позволяет заполнять поля. И код, который я использую для проверки записей, является методом, поэтому точно такой же код, который находит значения во втором экземпляре, не может найти его в первом.
Любые предложения о том, что может происходить, или как я могу получить полные записи без отображения второго пользовательского интерфейса для пользователя?
Я использую пример кода 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;
}
РЕДАКТИРОВАТЬ: Добавление моего решения (спасибо Торстен!).
- (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;
}
1 ответ
Один человек может состоять из нескольких человек. Переберите всех людей, чтобы получить ваши данные:
NSArray *people = (NSArray *)CFBridgingRelease(ABPersonCopyArrayOfAllLinkedPeople(person));
...
ABRecordRef user = CFBridgingRetain([people objectAtIndex:i]);
...
valuesRef = ABRecordCopyValue(user, kABPersonPhoneProperty);
valuesCount = 0;
if (valuesRef != nil) valuesCount = ABMultiValueGetCount(valuesRef);
...
НТН