获取并格式化联系人姓名和地址 swift 5

Fetching and formatting contact name and address swift 5

我正在从联系人列表中提取联系人姓名、邮寄地址和组织,但我有一些问题。我正在获取联系人标识符并将其存储到 SQLite 数据库中。然后我从数据库中提取 ID 并将其传递给函数。 IE。 contactID 这很好用。但是,我有 1 个问题,我有一个问题。

问题: 除非联系人地址为空,否则一切正常。在这种情况下,"if let" 语句会抛出此错误。我认为 "if let" 应该可以防止这种情况发生。由于未捕获的异常 'NSRangeException' 而终止应用程序,原因:'*** -[__NSArray0 objectAtIndex:]:索引 0 超出空 NSArray 的范围'

我该怎么做才能解决这个问题,还是我把自己逼到了墙角?

我也有一个问题。如何检查联系人是否有多个邮寄地址?如果有多个 mailingAddresses,那么我的计划是显示一个警报,以允许用户选择要使用的地址。显示警报不是问题,我只需要检查和获取地址方面的帮助。

func getContactFromID_Ouote(contactID: String)
    {
        let store = CNContactStore()
        var theName = CNContact()

        let theKeys = [CNContactNamePrefixKey,
                       CNContactGivenNameKey,
                       CNContactFamilyNameKey,
                       CNContactOrganizationNameKey,
                       CNContactPostalAddressesKey,
                       CNContactFormatter.descriptorForRequiredKeys(for: .fullName)] as! [CNKeyDescriptor]

        do {
            theName = try store.unifiedContact(withIdentifier: contactID, keysToFetch: theKeys)

            contactName = CNContactFormatter.string(from: theName, style: .fullName)!

            contactPrefix = theName.namePrefix
            contactFirst = theName.givenName
            contactLast = theName.familyName
            companyName = theName.organizationName == "" ? "" : theName.organizationName

        } catch {
            print("Fetching contact data failed: \(error)")
        }

        if let addressString = (((theName.postalAddresses[0] as AnyObject).value(forKey: "labelValuePair") as AnyObject).value(forKey: "value")) as? CNPostalAddress
        {
            mailAddress = CNPostalAddressFormatter.string(from: addressString, style: .mailingAddress)
        }
}

首先,if let 会检查 addressString 是否为 nil。而不是这个表达式的部分。
(((theName.postalAddresses[0] as AnyObject).value(forKey: "labelValuePair") as AnyObject).value(forKey: "value")) as? CNPostalAddress

上面的表达式是一步一步执行的,比如先执行(theName.postalAddresses[0] as AnyObject),然后执行
,然后执行value(forKey: "labelValuePair") as AnyObject),然后执行
,然后执行.value(forKey: "value")) as? CNPostalAddress。 =28=] 如果这些表达式中的任何一个为 nil,它就会崩溃,但只有当最后一个表达式即 value(forKey: "value")) as? CNPostalAddress 为 nil 时,它才不会崩溃并按照您的预期工作。

第二件事是 theName.postalAddresses[0] 使用下标来获取索引 0 处的对象,并且它总是被强制解包。因此它不会检查 nil 并崩溃。
你必须做的是这样的事情。

if let firstPostalAddress = (theName.postalAddresses.first as? AnyObject),
                let labelValuePair = firstPostalAddress.value(forKey: "labelValuePair") as? AnyObject,
            let finalPostalAddress = labelValuePair.value(forKey: "value") as? CNPostalAddress
            {
                mailAddress = CNPostalAddressFormatter.string(from: finalPostalAddress, style: .mailingAddress)

}

所以你正在做的是检查每个对象是否为 nil。 希望这有帮助。