【问题标题】:Fetching and formatting contact name and address swift 5快速获取和格式化联系人姓名和地址 5
【发布时间】:2020-02-06 02:16:10
【问题描述】:

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

问题: 除非联系人地址为空,否则一切正常。在这种情况下,“if let”语句会引发此错误。我认为“如果让”应该防止这种情况。由于未捕获的异常“NSRangeException”而终止应用程序,原因:“*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray”

我能做些什么来解决这个问题,还是我把自己编码到了一个角落?

我还有一个问题。如何检查联系人是否有多个 mailingAddresses?如果有多个 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)
        }
}

【问题讨论】:

    标签: ios swift5 xcode11.3


    【解决方案1】:

    首先,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
    如果这些表达式中的任何一个为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。 希望这会有所帮助。

    【讨论】:

    • 谢谢。那确实解决了崩溃。感谢您解释原因并且不只是发布代码。但是,我收到您的解决方案的 2 个警告。 'CNLabeledValue?' 的条件转换到“AnyObject”总是成功所以我在第一行取出了演员表,它似乎工作正常。我在第二行收到此警告。我投的是 CNPostalAddress ,这似乎也有效。 'Any?' 的条件转换到“AnyObject”总是成功再次感谢。 – Quailcreek 9 分钟前
    • 是的,因为我只是在答案本身中格式化了代码,所以我没有在 XCode 中检查它。很高兴它成功了。
    • 那么您建议我如何检查多个邮寄地址?
    • 已经有一段时间没有在 Contact 框架上工作了。也许您发布了一个新问题,仅包含该部分,您可以更快地找到帮助,也许还有更好的答案。
    猜你喜欢
    • 2017-03-28
    • 2012-10-11
    • 1970-01-01
    • 2012-08-27
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多