简体   繁体   English

您如何快速访问用户联系人中的电话号码?

[英]How do you access a phone number from your user's contacts in swift?

Here is my code for getting the name of a contact, how would I go about getting their phone number?这是我获取联系人姓名的代码,我将如何获取他们的电话号码?

func createAddressBook() -> Bool {
    if self.addressBook != nil {
        return true
    }
    var err : Unmanaged<CFError>? = nil
    let addressBook : ABAddressBook? = ABAddressBookCreateWithOptions(nil, &err).takeRetainedValue()
    if addressBook == nil {
        println(err)
        self.addressBook = nil
        return false
    }
    self.addressBook = addressBook
    getContactNames()
    return true
}

func getContactNames() {
    if !self.determineStatus() {
        println("not authorized")
        return
    }
    let people = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue() as NSArray as [ABRecord]
    for person in people {
        var contactName = ABRecordCopyCompositeName(person).takeRetainedValue() as String
        self.contacts.append(contact(name: contactName))
    }
}

Any help would be greatly appreciated.任何帮助将不胜感激。

As of iOS 9, we would use Contacts framework, in which phoneNumbers is a CNLabeledValue<CNPhoneNumber> :从 iOS 9 开始,我们将使用 Contacts 框架,其中phoneNumbersCNLabeledValue<CNPhoneNumber>

let status = CNContactStore.authorizationStatus(for: .contacts)
if status == .denied || status == .restricted {
    presentSettingsAlert()
    return
}

// open it

let store = CNContactStore()
store.requestAccess(for: .contacts) { granted, error in
    guard granted else {
        self.presentSettingsAlert()
        return
    }
    
    // get the contacts
    
    let request = CNContactFetchRequest(keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: .fullName), CNContactPhoneNumbersKey as CNKeyDescriptor])
    do {
        try store.enumerateContacts(with: request) { contact, stop in
            let name = CNContactFormatter.string(from: contact, style: .fullName)
            print(name)
            
            for phone in contact.phoneNumbers {
                var label = phone.label
                if label != nil {
                    label = CNLabeledValue<CNPhoneNumber>.localizedString(forLabel: label!)
                }
                print("  ", label, phone.value.stringValue)
            }
        }
    } catch {
        print(error)
    }
}

Where在哪里

private func presentSettingsAlert() {
    let settingsURL = URL(string: UIApplicationOpenSettingsURLString)!
    
    DispatchQueue.main.async {
        let alert = UIAlertController(title: "Permission to Contacts", message: "This app needs access to contacts in order to ...", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Go to Settings", style: .default) { _ in
            UIApplication.shared.openURL(settingsURL)
        })
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
        self.present(alert, animated: true)
    }
}

Prior to iOS 9, you would use the AddressBook framework, in which the phone numbers is a ABMultiValueRef , so get that reference and then iterate through the phone numbers:在 iOS 9 之前,您将使用 AddressBook 框架,其中电话号码是ABMultiValueRef ,因此获取该引用,然后遍历电话号码:

// make sure user hadn't previously denied access

let status = ABAddressBookGetAuthorizationStatus()
if status == .denied || status == .restricted {
    presentSettingsAlert()
    return
}

// open it

var error: Unmanaged<CFError>?
guard let addressBook: ABAddressBook? = ABAddressBookCreateWithOptions(nil, &error)?.takeRetainedValue() else {
    print(String(describing: error?.takeRetainedValue()))
    return
}

// request permission to use it

ABAddressBookRequestAccessWithCompletion(addressBook) { granted, error in
    if !granted {
        self.presentSettingsAlert()
        return
    }
    
    guard let people = ABAddressBookCopyArrayOfAllPeople(addressBook)?.takeRetainedValue() as [ABRecord]? else {
        print("unable to get contacts")
        return
    }
    
    for person in people {
        let name = ABRecordCopyCompositeName(person)?.takeRetainedValue() as String?
        print(name)
        
        if let phoneNumbers: ABMultiValue = ABRecordCopyValue(person, kABPersonPhoneProperty)?.takeRetainedValue() {
            for index in 0 ..< ABMultiValueGetCount(phoneNumbers) {
                let number = ABMultiValueCopyValueAtIndex(phoneNumbers, index)?.takeRetainedValue() as? String
                let label  = ABMultiValueCopyLabelAtIndex(phoneNumbers, index)?.takeRetainedValue()
                print("  ", self.localizedLabel(label), number)
            }
        }
    }
}

MacOS has an existing routine to localize that label, but I don't know of any such public function in AddressBook framework for iOS, so you may want to convert it yourself (or populate localization table for NSLocalizedString ): MacOS 有一个现有的例程来本地化该标签,但我不知道 iOS 的 AddressBook 框架中有任何此类公共函数,因此您可能想要自己转换它(或为NSLocalizedString填充本地化表):

// frankly, you probably should just use `NSLocalizedString()` and fill the table with these values

private func localizedLabel(_ label: CFString?) -> String? {
    guard let label = label else {
        return nil
    }
    
    if CFStringCompare(label, kABHomeLabel, []) == .compareEqualTo {            // use `[]` for options in Swift 2.0
        return "Home"
    } else if CFStringCompare(label, kABWorkLabel, []) == .compareEqualTo {
        return "Work"
    } else if CFStringCompare(label, kABOtherLabel, []) == .compareEqualTo {
        return "Other"
    } else if CFStringCompare(label, kABPersonPhoneMobileLabel, []) == .compareEqualTo {
        return "Mobile"
    } else if CFStringCompare(label, kABPersonPhoneIPhoneLabel, []) == .compareEqualTo {
        return "iPhone"
    } else if CFStringCompare(label, kABPersonPhoneMainLabel, []) == .compareEqualTo {
        return "Main"
    } else if CFStringCompare(label, kABPersonPhoneHomeFAXLabel, []) == .compareEqualTo {
        return "Home fax"
    } else if CFStringCompare(label, kABPersonPhoneWorkFAXLabel, []) == .compareEqualTo {
        return "Work fax"
    } else if CFStringCompare(label, kABPersonPhoneOtherFAXLabel, []) == .compareEqualTo {
        return "Other fax"
    } else if CFStringCompare(label, kABPersonPhonePagerLabel, []) == .compareEqualTo {
        return "Pager"
    } else {
        return label as String
    }
}

For Swift 2, see previous revision of this answer .对于 Swift 2,请参阅此答案的先前修订版

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Swift 获取用户的联系人电话号码 - Swift Fetching User's Contacts Phone Numbers 您如何仅从iOS联系人中检索select属性? - How do you retrieve ONLY the select property from your iOS contacts? 如何使用Swift中的“联系人”框架获取具有手机号码的所有联系人? - How can I get all contacts with a mobile phone number using Contacts framework in Swift? 如何从 Swift 中的 Parse 查询结果访问对象的字段? - How do you access an object's fields from a Parse query result in Swift? 如何在Swift中将keychain的访问权限设置为kSecAttrAccessibleAfterFirstUnlock? - How do you set the keychain's access to be kSecAttrAccessibleAfterFirstUnlock in Swift? Swift使用Contacts Framework,使用电话号码搜索以获取名称和用户图像 - Swift Using Contacts Framework, search using phone number to get Name and User Image 如何验证设备通讯录中的电话号码是否为手机(手机)? - How do I verify if a phone number in device contacts is a cell phone (mobile)? 如何获取用户的电话号码? - How to get user's phone number? 如何在 flutter 中获取用户的电话号码 - how to get user's phone number in flutter 如何使用Predicate通过电话号码过滤领域联系人? - How to filter realm contacts by phone number with Predicate?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM