需要创建自定义视图,如 ABPeoplePickerNavigationController
Need to create a custom view like ABPeoplePickerNavigationController
我想创建一个自定义视图,就像 iPhone 中的联系人一样。是否有任何教程可以像 ABPeoplePickerNavigationController 一样制作自定义视图?
请注意,我不想打开 AddressBookUI 框架提供的默认人员选取器控制器。另外,我确实想将这个导航控制器绑定到我的主视图中。
为了参考我真正想要的,您可以参考 iOS 设备上 Whatsapp 的联系人选项卡。
编辑:我已经有了一个联系人列表,并在 table 视图中显示了联系人的名字和姓氏。现在,我想为 A-Z 中的字母表创建索引,点击该索引后,table 视图应滚动到该联系人。另外,如何实现搜索功能以通过他/她的名字或姓氏查找用户?
看看这个:http://www.appcoda.com/ios-programming-index-list-uitableview/
table 的方法查看帮助给出您想要的结果:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
和
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title
我目前正在构建的应用程序中有完全相同的东西,我们也从 Whatsapp 等应用程序中获得了联系人方面的灵感。
我使用了一个带有自定义单元格的简单表格视图,仅包含名称和图片。
我的过程如下:
- 在 coredata 中创建一个
contact
对象(或另一种持久保存数据的方式)
通过 ABAddressbook
框架,您可以浏览所有联系人并将它们转换为新的联系人对象。在您的 Contact
对象中保留您的 ABPerson
的引用,这将允许您稍后仅使用引用来查找和更新您的联系人。如果不这样做,则每次要更新联系人时都必须浏览所有 ABPersons。
您可以直接使用 ABPersons,但编写代码真的很痛苦。
提取完所有联系人后,如果使用核心数据,请确保保存上下文,或者将它们存储在 .sqlite 中。
- 然后您可以简单地将它们提取到联系人数组中,并在您选择的自定义单元格中显示它们。
This appcoda tutorial 是一个不错的表格视图自定义单元格教程。只需通过谷歌搜索“tableview custom cell ios”并找到您可能喜欢的不同内容,您就可以找到另外一千个。最后,您将只有一个带有标签和图片的单元格,您可以使用我用于另一个 "contact" 类型的表格视图的简单 UITableViewCell
。
保持联系人列表最新(获取正确的号码、图片、姓名等)并在更新前确保它们存在,检查联系人是否已被删除、添加等。所有这些都必须完成为了使您的列表准确无误,这是一个相当不错的 long/annoying 过程。
我可以分享我的联系方式 class 但它包含很多与您无关的代码,可能会让您感到困惑,因为:
- 我也在检查这些联系人是否已经是我的应用程序的用户,以便将他们移动到我的表格视图的特定部分
- 我将我的表格视图分成 27 个部分(用户,然后是字母)。
此外,我将用最后一条通用编程建议来结束它:最好先准确地写下你需要什么和你将需要什么,把所有的可能性写在纸上, etc. 遇到了很多简单的问题,我花了一段时间才解决,要么是我没有计划好,要么是因为它被隐藏了。
例如:
- 您的某些联系人根本没有姓名。
- 您的某些联系人在 "Title" 字段(您写医生或先生)中有姓名
- 您的某些联系人没有 phone 号码(如果您使用 phone 号码作为标识符)
- 您的一些联系人具有国际格式,而另一些则没有(+32 46556555 或 0032 46556555)
- 您的一些联系人有用相机拍摄的照片,另一些来自 Gmail,格式不同
- 由于用户同步不佳,您可能有重复的联系人(同名,所有内容都相同)
- 您需要确保 firstname/lastname 在正确的部分,区分大小写的编码会造成麻烦
- 您需要为以笑脸字符或非字母数字字符开头的联系人找到解决方案
- 您的用户将需要一个索引列表
- 当然你需要添加一个搜索栏,因为有些人有超过 1000 个联系人。
- 以后还会有更多,我保证。
因为这是非常特定于应用程序的,所以我不会讨论我遇到的每一个问题以及我为此所做的工作,但是你明白了:)尽管有任何非常具体的问题,但我可能会问已经有了一个非常具体的解决方案,因为我几乎不得不从头开始复制 whatsapp 的联系人,见鬼,我做到了。 (我实际上得到了与 Anonymess 和 iOS 完全相同的结果)
编辑:这是我的 ABPerson 提取方法的一些方法; ContactDAO 主要与我的持久模型 (CoreData) 交互,我相信它们的名称足够清晰,您可以理解正在发生的事情。我对评论和变量名感到满意,因此您应该可以轻松阅读它。
这里出现了一大段代码。
- (NSMutableArray *)getAllRecordsWithPeople:(CFArrayRef)allPeople andAddressBook:(ABAddressBookRef)addressbook{
NSMutableArray *newRecords = [[NSMutableArray alloc]init];
CFIndex nPeople = ABAddressBookGetPersonCount(addressbook);
for (int i=0;i < nPeople;i++){
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
ABRecordID refId = ABRecordGetRecordID(ref);
NSNumber *recId = [NSNumber numberWithInt:refId];
[newRecords addObject:recId];
}
return newRecords;
}
- (void)getValidContactsFromAddressBookWithCompletionBlock:(void (^)(NSError *error))completion{
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, nil);
__block BOOL accessGranted = NO;
if (&ABAddressBookRequestAccessWithCompletion != NULL) {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
if (accessGranted) {
NSMutableArray *newRecords = [[NSMutableArray alloc]init];
NSMutableArray *updatedRecords = [[NSMutableArray alloc]init];
NSMutableArray *unchangedRecords = [[NSMutableArray alloc]init];
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
//Checking the last time we updated
NSTimeInterval lastSyncTime;
if ([[NSUserDefaults standardUserDefaults]objectForKey:@"LastSyncTime"] == nil){
//This is the first time we update.
lastSyncTime = 0;
}else{
//Setting the last update in variable
lastSyncTime = [[[NSUserDefaults standardUserDefaults]objectForKey:@"LastSyncTime"]doubleValue];
}
if (lastSyncTime == 0){
//We have to insert everyone, this is the first time we do this.
newRecords = [self getAllRecordsWithPeople:allPeople andAddressBook:addressBook];
}else{
//We have to manually compare everyone to see if something has changed.
for (int i=0;i < nPeople;i++) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
ABRecordID refId = ABRecordGetRecordID(ref);
NSNumber *recId = @(refId);
CFDateRef recordCreation = ABRecordCopyValue(ref, kABPersonCreationDateProperty);
NSDate *recCreDate = (__bridge NSDate *)(recordCreation);
NSTimeInterval creDateInterval = [recCreDate timeIntervalSince1970];
if(creDateInterval > lastSyncTime){
//This object was created after my lastSync, this must be a new record
[newRecords addObject:recId];
}else{
//Checking the last update of the given record
CFDateRef recordUpdate = ABRecordCopyValue(ref, kABPersonModificationDateProperty);
NSDate *recUpDate = (__bridge NSDate*)(recordUpdate);
if ([recUpDate timeIntervalSince1970] > lastSyncTime){
//The record was somehow updated since last time, we'll update it
[updatedRecords addObject:recId];
}else{
//The record wasn't updated nor created, it is therefore unchanged.
//We still need to keep it in a separate array to compare deleted contacts
[unchangedRecords addObject:recId];
}
}
}
if(allPeople)
CFRelease(allPeople);
}
[self manageNewContacts:newRecords updatedContacts:updatedRecords andUnchangedContacts:unchangedRecords inAddressBook:addressBook andBlock:^(NSError *error) {
completion(error);
}];
}else{
NSError *error = [NSError errorWithDomain:@"ABAccess access forbidden" code:403 userInfo:nil];
completion(error);
}
}
- (void)manageNewContacts:(NSMutableArray*)newRecords updatedContacts:(NSMutableArray*)updatedRecords andUnchangedContacts:(NSMutableArray*)unchangedRecords inAddressBook:(ABAddressBookRef)addressbook andBlock:(void (^)(NSError *error))completion{
AppDelegate *app = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = app.managedObjectContext;
//Getting all the CoreData contacts IDs to have something to compare
NSArray *coreDataContactsIds = [ContactDAO getAllContactIdsInManagedObjectContext:context];
for (NSDictionary *rec in coreDataContactsIds){
NSNumber *recId = rec[@"record_id"];
if (![unchangedRecords containsObject:recId]){
//The unchanged record doesn't exist locally
if (![updatedRecords containsObject:recId]){
//The updated record doesn't exist locally
if (![newRecords containsObject:recId]){
//The new record doesn't exist locally
//That means the ongoing record has been deleted from the addressbook,
//we also have to delete it locally
[ContactDAO deleteContactWithID:recId inManagedObjectContext:context];
}
}
}
}
for (NSNumber *recId in updatedRecords){
ABRecordID recordID = (ABRecordID)recId.intValue;
ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressbook, recordID);
NSDictionary *personDict = [self getPersonDictionaryFromABRecordRef:person];
if (personDict){
[ContactDAO updateContactWithFirstName:personDict[@"firstName"] lastName:personDict[@"lastName"] compositeName:personDict[@"compositeName"] picture:personDict[@"picture"] phoneNumbers:personDict[@"phoneNumbers"] recordID:recId inManagedObjectContext:context];
}
}
for (NSNumber *recId in newRecords){
ABRecordID recordID = (ABRecordID)recId.intValue;
ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressbook, recordID);
NSDictionary *personDict = [self getPersonDictionaryFromABRecordRef:person];
if (personDict){
[ContactDAO createContactWithFirstName:personDict[@"firstName"] lastName:personDict[@"lastName"] compositeName:personDict[@"compositeName"] picture:personDict[@"picture"] phoneNumbers:personDict[@"phoneNumbers"] recordID:recId inManagedObjectContext:context];
}
}
NSError *dbError;
[context save:&dbError];
NSTimeInterval lastSyncTime = [[NSDate date]timeIntervalSince1970];
[[NSUserDefaults standardUserDefaults]setObject:@(lastSyncTime) forKey:@"LastSyncTime"];
completion(dbError);
}
- (NSDictionary*)getPersonDictionaryFromABRecordRef:(ABRecordRef)person{
//Get name
NSString * firstName, *lastName;
firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
lastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
firstName = (firstName == nil) ? @"" : firstName;
lastName = (lastName == nil) ? @"" : lastName;
NSString *compositeName;
if ([firstName isEqualToString:@""] && [lastName isEqualToString:@""]){
return nil;
}
if ([lastName isEqualToString:@""]){
compositeName = [NSString stringWithFormat:@"%@", firstName];
}
if ([firstName isEqualToString:@""]){
compositeName = [NSString stringWithFormat:@"%@", lastName];
}
if (![lastName isEqualToString:@""] && ![firstName isEqualToString:@""]){
compositeName = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
}
//Get picture
CFDataRef imageData = ABPersonCopyImageData(person);
NSData *data = CFBridgingRelease(imageData);
//Get phone numbers
NSMutableSet *phoneNumbers = [[NSMutableSet alloc]init];
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for(CFIndex i = 0; i < ABMultiValueGetCount(phones); i++) {
CFStringRef str = ABMultiValueCopyValueAtIndex(phones, i);
NSString *num = CFBridgingRelease(str);
[phoneNumbers addObject:num];
/*if(str)
CFRelease(str);*/
}
//Save it in dictionary
NSDictionary *personDict = [[NSDictionary alloc]initWithObjectsAndKeys:firstName, @"firstName",lastName , @"lastName",phoneNumbers,@"phoneNumbers", compositeName, @"compositeName", data, @"picture", nil];
//Release everything.
if(phones)
CFRelease(phones);
return personDict;
}
关于索引,this tutorial 应该没问题。
我想创建一个自定义视图,就像 iPhone 中的联系人一样。是否有任何教程可以像 ABPeoplePickerNavigationController 一样制作自定义视图?
请注意,我不想打开 AddressBookUI 框架提供的默认人员选取器控制器。另外,我确实想将这个导航控制器绑定到我的主视图中。
为了参考我真正想要的,您可以参考 iOS 设备上 Whatsapp 的联系人选项卡。
编辑:我已经有了一个联系人列表,并在 table 视图中显示了联系人的名字和姓氏。现在,我想为 A-Z 中的字母表创建索引,点击该索引后,table 视图应滚动到该联系人。另外,如何实现搜索功能以通过他/她的名字或姓氏查找用户?
看看这个:http://www.appcoda.com/ios-programming-index-list-uitableview/
table 的方法查看帮助给出您想要的结果:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
和
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title
我目前正在构建的应用程序中有完全相同的东西,我们也从 Whatsapp 等应用程序中获得了联系人方面的灵感。
我使用了一个带有自定义单元格的简单表格视图,仅包含名称和图片。
我的过程如下:
- 在 coredata 中创建一个
contact
对象(或另一种持久保存数据的方式) 通过
ABAddressbook
框架,您可以浏览所有联系人并将它们转换为新的联系人对象。在您的Contact
对象中保留您的ABPerson
的引用,这将允许您稍后仅使用引用来查找和更新您的联系人。如果不这样做,则每次要更新联系人时都必须浏览所有 ABPersons。 您可以直接使用 ABPersons,但编写代码真的很痛苦。提取完所有联系人后,如果使用核心数据,请确保保存上下文,或者将它们存储在 .sqlite 中。
- 然后您可以简单地将它们提取到联系人数组中,并在您选择的自定义单元格中显示它们。
This appcoda tutorial 是一个不错的表格视图自定义单元格教程。只需通过谷歌搜索“tableview custom cell ios”并找到您可能喜欢的不同内容,您就可以找到另外一千个。最后,您将只有一个带有标签和图片的单元格,您可以使用我用于另一个 "contact" 类型的表格视图的简单 UITableViewCell
。
保持联系人列表最新(获取正确的号码、图片、姓名等)并在更新前确保它们存在,检查联系人是否已被删除、添加等。所有这些都必须完成为了使您的列表准确无误,这是一个相当不错的 long/annoying 过程。
我可以分享我的联系方式 class 但它包含很多与您无关的代码,可能会让您感到困惑,因为: - 我也在检查这些联系人是否已经是我的应用程序的用户,以便将他们移动到我的表格视图的特定部分 - 我将我的表格视图分成 27 个部分(用户,然后是字母)。
此外,我将用最后一条通用编程建议来结束它:最好先准确地写下你需要什么和你将需要什么,把所有的可能性写在纸上, etc. 遇到了很多简单的问题,我花了一段时间才解决,要么是我没有计划好,要么是因为它被隐藏了。
例如:
- 您的某些联系人根本没有姓名。
- 您的某些联系人在 "Title" 字段(您写医生或先生)中有姓名
- 您的某些联系人没有 phone 号码(如果您使用 phone 号码作为标识符)
- 您的一些联系人具有国际格式,而另一些则没有(+32 46556555 或 0032 46556555)
- 您的一些联系人有用相机拍摄的照片,另一些来自 Gmail,格式不同
- 由于用户同步不佳,您可能有重复的联系人(同名,所有内容都相同)
- 您需要确保 firstname/lastname 在正确的部分,区分大小写的编码会造成麻烦
- 您需要为以笑脸字符或非字母数字字符开头的联系人找到解决方案
- 您的用户将需要一个索引列表
- 当然你需要添加一个搜索栏,因为有些人有超过 1000 个联系人。
- 以后还会有更多,我保证。
因为这是非常特定于应用程序的,所以我不会讨论我遇到的每一个问题以及我为此所做的工作,但是你明白了:)尽管有任何非常具体的问题,但我可能会问已经有了一个非常具体的解决方案,因为我几乎不得不从头开始复制 whatsapp 的联系人,见鬼,我做到了。 (我实际上得到了与 Anonymess 和 iOS 完全相同的结果)
编辑:这是我的 ABPerson 提取方法的一些方法; ContactDAO 主要与我的持久模型 (CoreData) 交互,我相信它们的名称足够清晰,您可以理解正在发生的事情。我对评论和变量名感到满意,因此您应该可以轻松阅读它。
这里出现了一大段代码。
- (NSMutableArray *)getAllRecordsWithPeople:(CFArrayRef)allPeople andAddressBook:(ABAddressBookRef)addressbook{
NSMutableArray *newRecords = [[NSMutableArray alloc]init];
CFIndex nPeople = ABAddressBookGetPersonCount(addressbook);
for (int i=0;i < nPeople;i++){
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
ABRecordID refId = ABRecordGetRecordID(ref);
NSNumber *recId = [NSNumber numberWithInt:refId];
[newRecords addObject:recId];
}
return newRecords;
}
- (void)getValidContactsFromAddressBookWithCompletionBlock:(void (^)(NSError *error))completion{
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, nil);
__block BOOL accessGranted = NO;
if (&ABAddressBookRequestAccessWithCompletion != NULL) {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
if (accessGranted) {
NSMutableArray *newRecords = [[NSMutableArray alloc]init];
NSMutableArray *updatedRecords = [[NSMutableArray alloc]init];
NSMutableArray *unchangedRecords = [[NSMutableArray alloc]init];
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
//Checking the last time we updated
NSTimeInterval lastSyncTime;
if ([[NSUserDefaults standardUserDefaults]objectForKey:@"LastSyncTime"] == nil){
//This is the first time we update.
lastSyncTime = 0;
}else{
//Setting the last update in variable
lastSyncTime = [[[NSUserDefaults standardUserDefaults]objectForKey:@"LastSyncTime"]doubleValue];
}
if (lastSyncTime == 0){
//We have to insert everyone, this is the first time we do this.
newRecords = [self getAllRecordsWithPeople:allPeople andAddressBook:addressBook];
}else{
//We have to manually compare everyone to see if something has changed.
for (int i=0;i < nPeople;i++) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
ABRecordID refId = ABRecordGetRecordID(ref);
NSNumber *recId = @(refId);
CFDateRef recordCreation = ABRecordCopyValue(ref, kABPersonCreationDateProperty);
NSDate *recCreDate = (__bridge NSDate *)(recordCreation);
NSTimeInterval creDateInterval = [recCreDate timeIntervalSince1970];
if(creDateInterval > lastSyncTime){
//This object was created after my lastSync, this must be a new record
[newRecords addObject:recId];
}else{
//Checking the last update of the given record
CFDateRef recordUpdate = ABRecordCopyValue(ref, kABPersonModificationDateProperty);
NSDate *recUpDate = (__bridge NSDate*)(recordUpdate);
if ([recUpDate timeIntervalSince1970] > lastSyncTime){
//The record was somehow updated since last time, we'll update it
[updatedRecords addObject:recId];
}else{
//The record wasn't updated nor created, it is therefore unchanged.
//We still need to keep it in a separate array to compare deleted contacts
[unchangedRecords addObject:recId];
}
}
}
if(allPeople)
CFRelease(allPeople);
}
[self manageNewContacts:newRecords updatedContacts:updatedRecords andUnchangedContacts:unchangedRecords inAddressBook:addressBook andBlock:^(NSError *error) {
completion(error);
}];
}else{
NSError *error = [NSError errorWithDomain:@"ABAccess access forbidden" code:403 userInfo:nil];
completion(error);
}
}
- (void)manageNewContacts:(NSMutableArray*)newRecords updatedContacts:(NSMutableArray*)updatedRecords andUnchangedContacts:(NSMutableArray*)unchangedRecords inAddressBook:(ABAddressBookRef)addressbook andBlock:(void (^)(NSError *error))completion{
AppDelegate *app = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = app.managedObjectContext;
//Getting all the CoreData contacts IDs to have something to compare
NSArray *coreDataContactsIds = [ContactDAO getAllContactIdsInManagedObjectContext:context];
for (NSDictionary *rec in coreDataContactsIds){
NSNumber *recId = rec[@"record_id"];
if (![unchangedRecords containsObject:recId]){
//The unchanged record doesn't exist locally
if (![updatedRecords containsObject:recId]){
//The updated record doesn't exist locally
if (![newRecords containsObject:recId]){
//The new record doesn't exist locally
//That means the ongoing record has been deleted from the addressbook,
//we also have to delete it locally
[ContactDAO deleteContactWithID:recId inManagedObjectContext:context];
}
}
}
}
for (NSNumber *recId in updatedRecords){
ABRecordID recordID = (ABRecordID)recId.intValue;
ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressbook, recordID);
NSDictionary *personDict = [self getPersonDictionaryFromABRecordRef:person];
if (personDict){
[ContactDAO updateContactWithFirstName:personDict[@"firstName"] lastName:personDict[@"lastName"] compositeName:personDict[@"compositeName"] picture:personDict[@"picture"] phoneNumbers:personDict[@"phoneNumbers"] recordID:recId inManagedObjectContext:context];
}
}
for (NSNumber *recId in newRecords){
ABRecordID recordID = (ABRecordID)recId.intValue;
ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressbook, recordID);
NSDictionary *personDict = [self getPersonDictionaryFromABRecordRef:person];
if (personDict){
[ContactDAO createContactWithFirstName:personDict[@"firstName"] lastName:personDict[@"lastName"] compositeName:personDict[@"compositeName"] picture:personDict[@"picture"] phoneNumbers:personDict[@"phoneNumbers"] recordID:recId inManagedObjectContext:context];
}
}
NSError *dbError;
[context save:&dbError];
NSTimeInterval lastSyncTime = [[NSDate date]timeIntervalSince1970];
[[NSUserDefaults standardUserDefaults]setObject:@(lastSyncTime) forKey:@"LastSyncTime"];
completion(dbError);
}
- (NSDictionary*)getPersonDictionaryFromABRecordRef:(ABRecordRef)person{
//Get name
NSString * firstName, *lastName;
firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
lastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
firstName = (firstName == nil) ? @"" : firstName;
lastName = (lastName == nil) ? @"" : lastName;
NSString *compositeName;
if ([firstName isEqualToString:@""] && [lastName isEqualToString:@""]){
return nil;
}
if ([lastName isEqualToString:@""]){
compositeName = [NSString stringWithFormat:@"%@", firstName];
}
if ([firstName isEqualToString:@""]){
compositeName = [NSString stringWithFormat:@"%@", lastName];
}
if (![lastName isEqualToString:@""] && ![firstName isEqualToString:@""]){
compositeName = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
}
//Get picture
CFDataRef imageData = ABPersonCopyImageData(person);
NSData *data = CFBridgingRelease(imageData);
//Get phone numbers
NSMutableSet *phoneNumbers = [[NSMutableSet alloc]init];
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for(CFIndex i = 0; i < ABMultiValueGetCount(phones); i++) {
CFStringRef str = ABMultiValueCopyValueAtIndex(phones, i);
NSString *num = CFBridgingRelease(str);
[phoneNumbers addObject:num];
/*if(str)
CFRelease(str);*/
}
//Save it in dictionary
NSDictionary *personDict = [[NSDictionary alloc]initWithObjectsAndKeys:firstName, @"firstName",lastName , @"lastName",phoneNumbers,@"phoneNumbers", compositeName, @"compositeName", data, @"picture", nil];
//Release everything.
if(phones)
CFRelease(phones);
return personDict;
}
关于索引,this tutorial 应该没问题。