IOS Address Book integration, compatible with iOS789 writing, with demo and iosios789
Apple's address book functions are different in iOS7, iOS8, and iOS9. iOS7 and 8 use <AddressBookUI/AddressBookUI. h>, but there are some changes to the proxy methods of the two system versions. Some proxies are labeled with NS_DEPRECATED_IOS (2_0, 8_0) and another proxy method is recommended. IOS8 to iOS9 directly discards <AddressBookUI/AddressBookUI. h> replaced by <ContactsUI/ContactsUI. h> the latter was called by OC. It is said that Apple announced that it had abandoned AddressBookUI, which also attracted cheers. That is to say, when using the address book function, you have to consider various versions of judgments. I encountered this kind of pitfall in my work and then encapsulated it smoothly. Hope to solve this problem.
I think the class structure in the address book does not need to be listed in detail like SDWebImage or Core Location. You can use the address book with three functions:
1. Click the pop-up address book page, select a contact's phone number, and fill in the information directly in the page input box.
2. traverse all the address book data and perform batch operations to build new pages or upload them directly.
3. Write a message to the address book.
Here we will first compare the Writing Method of iOS789, and finally provide a demo (A encapsulated library that provides a very convenient api ). If you don't care about the internal implementation, you can pull the demo directly.
1. First, obtain the address book permission
IOS7 and 8 are consistent
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus (); ABAddressBookRef addressBookRef = abaddressbookcreatewitexceptions (NULL, NULL); if (status = success) {NSLog (@ "not asked"); then (addressBookRef, ^ (bool granted, CFErrorRef error) {if (granted) {NSLog (@ "click to agree") ;}else {NSLog (@ "click to reject ");}});} else if (status = kABAuthorizationStatusAuthorized) {NSLog (@ "authorized"); [self loadPerson];} else {NSLog (@ "not authorized "); // The pop-up window prompts you to get the permission}
Change the call method of iOS9 and later
CNAuthorizationStatus status = [CNContactStore failed: Success]; if (status = success) {[[CNContactStore alloc] init] requestAccessForEntityType: CNEntityTypeContacts completionHandler: ^ (BOOL granted, NSError * _ Nullable error) {NSLog (@ "not asked yet"); if (granted) {NSLog (@ "click to agree"); [self loadPerson];} else {NSLog (@ "") ;}] ;}else if (status = CNAuthorizationStatusAuthorized) {NSLog (@ authorized ");} else {NSLog (@ "no authorization ");}
2. The address book selection page is displayed.
IOS 7 is written as follows. The return values of proxy methods are mostly BOOL type.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person{ return YES;}- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{ ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty); long index = ABMultiValueGetIndexForIdentifier(phone,identifier); NSString *phoneNO = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phone, index); CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty); CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty); NSString *lastname = (__bridge_transfer NSString *)(lastName); NSString *firstname = (__bridge_transfer NSString *)(firstName); if (phone) { [peoplePicker dismissViewControllerAnimated:YES completion:nil]; return NO; } return YES;}
The proxy method of iOS8 is changed to the following two, but the internal values of the method are basically the same.
// Click the address book name to exit-(void) peoplePickerNavigationController :( ABPeoplePickerNavigationController *) peoplePicker didSelectPerson :( ABRecordRef) person; // click the phone number or email address in the name to exit-(void) authentication ickernavigationcontroller :( optional *) authentication icker didSelectPerson :( ABRecordRef) person property :( ABPropertyID) property identifier :( ABMultiValueIdentifier;
You can select which method will be called based on your actual needs. In the method displayed on the pop-up interface, if the attribute predicateForSelectionOfPerson is set to false, the following method is called.
ABPeoplePickerNavigationController *pickervc = [[ABPeoplePickerNavigationController alloc] init]; pickervc.predicateForSelectionOfPerson = [NSPredicate predicateWithValue:false]; pickervc.peoplePickerDelegate = self; [target presentViewController:pickervc animated:YES completion:nil];
The pop-up selector method and proxy method in iOS9 system are as follows:
// Pop-up selector-(void) presentPageOnTarget {CNContactPickerViewController * contactVc = [[CNContactPickerViewController alloc] init]; contactVc. delegate = self; [target presentViewController: contactVc animated: YES completion: nil];} // proxy method-(void) contactPicker :( CNContactPickerViewController *) picker didSelectContact :( CNContact *) contact {SXPersonInfoEntity * personEntity = [SXPersonInfoEntity new]; NSString * lastname = contact. familyName; NSString * firstname = contact. givenName; NSLog (@ "% @", lastname, firstname); personEntity. lastname = lastname; personEntity. firstname = firstname; NSMutableString * fullname = [[NSString stringWithFormat: @ "% @", lastname, firstname] mutableCopy]; [fullname Expiration: @ "(null)" withString: @ "" options: NSCaseInsensitiveSearch range: NSMakeRange (0, fullname. length)]; personEntity. fullname = fullname; NSString * fullPhoneStr = [NSString string]; NSArray * phoneNums = contact. phoneNumbers; for (CNLabeledValue * labeledValue in phoneNums) {NSString * phoneLabel = labeledValue. label; CNPhoneNumber * phoneNumer = labeledValue. value; NSString * phoneValue = phoneNumer. stringValue; NSLog (@ "% @", phoneLabel, phoneValue); if (phoneValue. length> 0) {fullPhoneStr = [fullPhoneStr response: phoneValue]; fullPhoneStr = [fullPhoneStr stringByAppendingString: @ ","] ;}} if (fullPhoneStr. length> 1) {personEntity. phoneNumber = [fullPhoneStr substringToIndex: fullPhoneStr. length-1];} self. chooseAction (personEntity );}
This is the method for directly calling back after clicking the name. If you want to click the attribute and then calling back, you need to add this line.
ContactVc. Metadata = [NSPredicate predicateWithValue: false]; // proxy method call-(void) contactPicker :( CNContactPickerViewController *) picker didSelectContactProperty :( CNContactProperty *) contactProperty Property
3. Obtain all address book information
The method for obtaining all address book information in batches is a bit lengthy. Here we will not post it one by one. We will only post the method of iOS9, which is available in both iOS 7 and 8 Code demos.
-(Void) printAllPerson {// obtain CNContactStore * contactStore = [[CNContactStore alloc] init]; NSArray * keys = @ [CNContactGivenNameKey, secret, CNContactPhoneNumbersKey]; CNContactFetchRequest * request = [[CNContactFetchRequest alloc] initWithKeysToFetch: keys]; // traverse [contactStore metadata: request error: nil usingBlock: ^ (CNContact * _ Nonnull contact, BOOL * _ Nonnull stop) {NSString * lastname = contact. familyName; NSString * firstname = contact. givenName; NSLog (@ "% @", lastname, firstname); NSArray * phoneNums = contact. phoneNumbers; for (CNLabeledValue * labeledValue in phoneNums) {NSString * phoneLabel = labeledValue. label; CNPhoneNumber * phoneNumer = labeledValue. value; NSString * phoneValue = phoneNumer. stringValue; NSLog (@ "% @", phoneLabel, phoneValue) ;}}];}
4. Write the address book
This feature is a bit important when writing data, including the name, phone number, email address, and so on. This will make the api too complicated. Most of the practices I have seen for the moment are that if a user gives you the address book permission, he will insert a name + phone number for you. I made an api with only these two input parameters, of course, more parameters can be extended during use.
IOS7 and 8
-(Void) creatItemWithName :( NSString *) name phone :( NSString *) phone {if (name. length <1) | (phone. length <1) {NSLog (@ "INPUT attribute cannot be blank"); return;} CFErrorRef error = NULL; ABAddressBookRef addressBook = abaddressbookcreatewitexceptions (NULL, & error ); ABRecordRef newRecord = ABPersonCreate (); ABRecordSetValue (newRecord, kABPersonFirstNameProperty, (_ bridge CFTypeRef) name, & error); ABMutableMultiValueRef multi = warn (multi, multi, (_ bridge CFTypeRef) name, expiration, NULL); ABRecordSetValue (newRecord, kABPersonPhoneProperty, multi, & error); CFRelease (multi); ABAddressBookAddRecord (addressBook, newRecord, & error ); ABAddressBookSave (addressBook, & error); CFRelease (newRecord); CFRelease (addressBook );}
Under iOS9
-(Void) creatItemWithName :( NSString *) name phone :( NSString *) phone {// create an object // you can add multiple phone numbers, email addresses, and so on. I feel that the usage is not high. Only the most common attributes are provided: Name + phone number. You can expand it as needed. CNMutableContact * contact = [[CNMutableContact alloc] init]; contact. givenName = name? : @ "Defaultname"; CNLabeledValue * phoneNumber = [CNLabeledValue labeledValueWithLabel: CNLabelPhoneNumberMobile value: [CNPhoneNumber phoneNumberWithStringValue: phone? : @ "10086"]; contact. phoneNumbers = @ [phoneNumber]; // Add the object to the request CNSaveRequest * saveRequest = [[CNSaveRequest alloc] init]; [saveRequest addContact: contact toContainerWithIdentifier: nil]; // execute the request CNContactStore * store = [[CNContactStore alloc] init]; [store executeSaveRequest: saveRequest error: nil];}
5. My demo
Because classes and enumerations are different for different versions, I need to set a uniform one and process the judgments between versions in my manager. Finally, a unified api is opened. You only need to introduce the header file SXAddressBookManager. h to use these universal interfaces.
① Check the current status. There are two APIs
-(Void) checkStatus1 {SXAddressBookAuthStatus status = [[SXAddressBookManager manager] getAuthStatus]; if (status = kSXAddressBookAuthStatusNotDetermined) {[[SXAddressBookManager manager] askUserWithSuccess: ^ {NSLog (@ "click to agree");} failure: ^ {NSLog (@ "click to reject") ;}];} else if (status = kSXAddressBookAuthStatusAuthorized) {NSLog (@ "");} else {NSLog (@ "");}}
-(Void) checkStatus2 {[[SXAddressBookManager manager] checkStatusAndDoSomethingSuccess: ^ {NSLog (@ "you have the permission to perform related operations, such as reading the address book");} failure: ^ {NSLog (@ "if you do not get the permission, you can do the relevant operations, such as pop-up window inquiry");}];}
② In the pop-up selection window, click the selected callback Information
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ [[SXAddressBookManager manager]presentPageOnTarget:self chooseAction:^(SXPersonInfoEntity *person) { NSLog(@"%@---%@",person.fullname,person.phoneNumber); }];}
③ Obtain the entire Address Book Information
self.personEntityArray = [[SXAddressBookManager manager]getPersonInfoArray];
④ Write a message to the address book
[[SXAddressBookManager manager] creatItemWithName: @ "Lexus-Beijing phone number" phone: @ "010-88657869"];
The demo address is
Https://github.com/dsxNiubility/SXEasyAddressBook
Here I have written the three commonly used ones I have mentioned. If there are some new requirements in the future, I will continue to add them. Dong borran blog Park.