如何使用Swift检索地址簿联系人?

时间:2014-07-20 15:46:30

标签: swift contacts addressbook ios8

我不明白为什么我的代码不能用Swift编译。

我正在尝试转换此Objective-C代码:

CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);

  if (addressBook != nil) { 
    NSLog(@"Succesful."); 

    NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
}

这是我目前在Swift中的演绎:

var error:CFErrorRef
var addressBook = ABAddressBookCreateWithOptions(nil, nil);

if (addressBook != nil) {
    println("Succesful.");

    var allContacts:CFArrayRef = ABAddressBookCopyArrayOfAllPeople(addressBook);
}

但是,Xcode报道:

  

'Unmanaged'不能转换为'CFArrayRef'

你们有个主意吗?

1 个答案:

答案 0 :(得分:30)

显然,如果定位到iOS 9或更高版本,则根本不应使用AddressBook框架,而是使用Contacts框架。

所以,

  1. 导入Contacts

    import Contacts
    
  2. 确保在NSContactsUsageDescription中提供Info.plist

  3. 然后,您可以访问联系人。例如。在Swift 3:

    let status = CNContactStore.authorizationStatus(for: .contacts)
    if status == .denied || status == .restricted {
        presentSettingsActionSheet()
        return
    }
    
    // open it
    
    let store = CNContactStore()
    store.requestAccess(for: .contacts) { granted, error in
        guard granted else {
            DispatchQueue.main.async {
                self.presentSettingsActionSheet()
            }
            return
        }
    
        // get the contacts
    
        var contacts = [CNContact]()
        let request = CNContactFetchRequest(keysToFetch: [CNContactIdentifierKey as NSString, CNContactFormatter.descriptorForRequiredKeys(for: .fullName)])
        do {
            try store.enumerateContacts(with: request) { contact, stop in
                contacts.append(contact)
            }
        } catch {
            print(error)
        }
    
        // do something with the contacts array (e.g. print the names)
    
        let formatter = CNContactFormatter()
        formatter.style = .fullName
        for contact in contacts {
            print(formatter.string(from: contact) ?? "???")
        }
    }
    

    其中

    func presentSettingsActionSheet() {
        let alert = UIAlertController(title: "Permission to Contacts", message: "This app needs access to contacts in order to ...", preferredStyle: .actionSheet)
        alert.addAction(UIAlertAction(title: "Go to Settings", style: .default) { _ in
            let url = URL(string: UIApplicationOpenSettingsURLString)!
            UIApplication.shared.open(url)
        })
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
        present(alert, animated: true)
    }
    
  4. 我对AddressBook框架的原始答案如下。


    有几点意见:

    • 如果您想使用error的{​​{1}}参数,请将其定义为ABAddressBookCreateWithOptions

    • 如果失败,请查看错误对象(执行Unmanaged<CFError>?,以免泄漏)。

    • 确保地址簿的takeRetainedValue也一样,所以不要泄密。

    • 您可能不应该只是抓住联系人,但您可能应首先请求许可。

    将所有内容拉到一起得到:

    takeRetainedValue