面试题答案
一键面试实现更新电话号码功能的流程
- 引入AddressBook框架:在项目中导入
AddressBook.framework
和AddressBookUI.framework
头文件。
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
- 获取通讯录授权:使用
ABAddressBookRequestAccessWithCompletion
函数请求访问权限。
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion) {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
} else {
accessGranted = YES;
}
- 查找联系人:通过联系人的唯一标识(如
recordID
)或其他属性(如姓名等)查找要更新的联系人记录。
ABRecordRef contact = ABAddressBookGetPersonWithRecordID(addressBook, contactRecordID);
- 更新电话号码:
- 获取电话多值属性。
ABMutableMultiValueRef phoneNumbers = ABRecordCopyValue(contact, kABPersonPhoneProperty);
- 查找要更新的电话号码的索引(假设已知索引),或遍历查找特定号码。
CFIndex indexToUpdate = 0; // 假设索引为0
- 更新电话号码值。
ABMultiValueReplaceValueAtIndex(phoneNumbers, (__bridge CFStringRef)newPhoneNumber, indexToUpdate);
ABRecordSetValue(contact, kABPersonPhoneProperty, phoneNumbers, NULL);
- 保存更改:
CFErrorRef error = NULL;
if (!ABAddressBookSave(addressBook, &error)) {
NSLog(@"Error saving address book: %@", (__bridge NSError *)error);
}
- 释放资源:
CFRelease(phoneNumbers);
CFRelease(addressBook);
权限问题及解决方案
- 权限不足:
- 问题描述:如果用户拒绝了应用访问通讯录的权限,调用相关AddressBook API时会失败。
- 解决方案:在
ABAddressBookRequestAccessWithCompletion
的回调中检查权限是否授予。如果未授予,可以提示用户在设备的“设置”中手动开启应用对通讯录的访问权限。
if (!accessGranted) {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"权限不足" message:@"请在设置中允许应用访问通讯录" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
}
- 权限状态变化监听:
- 问题描述:应用运行过程中,用户可能在“设置”中更改应用对通讯录的访问权限,需要及时响应这种变化。
- 解决方案:注册
ABAddressBookChanged
通知。
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
NULL,
addressBookChangedCallback,
CFSTR(kABAddressBookChangedNotification),
addressBook,
CFNotificationSuspensionBehaviorCoalesce);
然后实现通知回调函数:
void addressBookChangedCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
// 重新检查权限并根据需要重新加载数据
}