Выборка и форматирование имени контакта и адреса swift 5 - PullRequest
0 голосов
/ 06 февраля 2020

Я вытаскиваю имя контакта, почтовый адрес и организацию из списка контактов, и у меня есть несколько вопросов. Я получаю идентификатор контакта и сохраняю его в БД SQLite. Затем я извлекаю идентификатор из БД и передаю его функции. ie. contactID Это отлично работает. Тем не менее, у меня есть 1 проблема, и у меня есть вопрос.

Проблема: все работает нормально, если адрес контакта не пуст. В этом случае операторы if if выдают эту ошибку. Я думал, что «если позволено» должно было предотвратить это. Завершение работы приложения из-за необработанного исключения «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)
        }
}

1 Ответ

1 голос
/ 06 февраля 2020

Прежде всего, if let проверит, равен ли addressString нулю или нет. И не части этого выражения.
(((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, оно будет иметь значение sh, но только если последнее выражение, то есть value(forKey: "value")) as? CNPostalAddress, равно нулю, оно не будет cra sh и будет работать в соответствии с вашими ожиданиями.

Во-вторых, 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)

}

Итак, вы проверяете для каждого объекта, является ли он нулевым или нет. Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...