iOS Swift: получить выбранный пользователем номер телефона из CNContactProperty в виде строки

Как следует из названия, в моем приложении iOS, использующем swift, у меня есть объект CNContactProperty, и я хочу извлечь из него номер телефона в виде строки.

Свойство CNContact возвращается из стандартного CNContactPickerViewController через функцию протокола делегата после того, как пользователь выбрал из него контакт.

Когда у контакта есть несколько телефонных номеров, я хочу иметь возможность извлечь тот, который пользователь нажал в представлении контакта, из CNContactProperty.

Я пытаюсь сделать что-то вроде этого:

 let myString = theCNContactProperty.value as! String

Однако это вылетает с ошибкой (lldb). Я подозреваю, что, может быть, свойство «значение» не то, что мне нужно?

Я могу получить произвольные числа следующим образом:

let myString = contactProperty.contact.phoneNumbers[0].value.stringValue

Который возвращает первый номер контакта. Однако это не служит моей цели, поскольку я хочу иметь возможность извлекать конкретный номер, выбранный пользователем, когда у контакта более 1 номера.

Я работаю над этим часами и не могу понять, я был бы признателен за любую помощь, которую вы можете мне оказать!

Изменить: это НЕ дубликат предоставленной ссылки. Связанный вопрос касается извлечения всех номеров из контакта, а НЕ конкретно выбранного. В этом есть ОГРОМНАЯ разница.


person b1skit    schedule 06.03.2017    source источник
comment
Какой тип theCNContactProperty.value?   -  person dan    schedule 06.03.2017
comment
Это значение любого типа. Я даже не уверен, что представляют его данные, но ценность наводит на мысль, что это может быть то, что я ищу. Однако, если я попытаюсь привести его к такой строке, я получу сбой: let test = contactProperty.value as! Нить   -  person b1skit    schedule 06.03.2017
comment
Второй показанный пример — единственный способ сделать это, поэтому вам придется придумать способ получить индекс выбранного числа.   -  person Timmy    schedule 06.03.2017
comment
@ b1skit Я знаю, что его объявленный тип Any, я спрашиваю, каков его фактический тип, когда вы к нему обращаетесь. Вы можете увидеть это в отладчике, установив точку останова в этой строке, или он должен печатать фактический тип в журнале сбоев, когда ваше приведение терпит неудачу.   -  person dan    schedule 06.03.2017
comment
Я не уверен, я думаю, что это какой-то указатель?? Вот копия/вставка из отладчика: test Any? some payload_data_0 Builtin.RawPointer 0xffffffff payload_data_2 Builtin.RawPointer 0x12255c4 0x012255c4 CoreFoundation__NSRetainCounters payload_data_2 Builtin.RawPointer 0x12255c4 0x012255c4 CoreFoundation__NSRetainCounters instance_type Builtin.RawPointer 0x69cadc 0x0069cadc ..... (подробнее)   -  person b1skit    schedule 06.03.2017
comment
Я не уверен, откуда вы это взяли, но я предполагаю, что ответ на мой вопрос заключается в том, что это CNPhoneNumber, и вам следует изменить as! String на as! CNPhoneNumber, а затем взять stringValue.   -  person dan    schedule 06.03.2017
comment
это правильный путь: (contactProperty.value as? CNPhoneNumber).stringValue если выбранное свойство просто CNContactPhoneNumbersKey   -  person Mahdi Moqadasi    schedule 07.10.2019


Ответы (2)


Итак, вы сказали, что хотите получить номер телефона, выбранный пользователем из CNContactViewController.

CNContactViewController имеет функцию делегата, которая возвращает ключ, выбранный пользователем. Это функция:

optional func contactViewController(_ viewController: CNContactViewController, 
  shouldPerformDefaultActionFor property: CNContactProperty) -> Bool

В этой функции вы можете получить выбранный номер телефона, выполнив следующие действия:

let myString = property.identifier

Кроме того, если вы вернете false в этой функции, действие не будет выполнено, что, я думаю, означает, что он не будет автоматически вызывать номер.

person Timmy    schedule 06.03.2017
comment
Я не могу заставить это работать. Я попытался добавить интерфейс CNContactViewControllerDelegate в свой класс и реализовать упомянутую вами функцию, но он не запускается CNContactPickerViewController. Кажется, что CNContactPickerViewController запускает только функции в CNContactPickerDelegate? - person b1skit; 06.03.2017
comment
Не могли бы вы обновить свой исходный пост этим кодом, чтобы я мог увидеть, как вы его реализовали? А также вы можете бороться с дубликатом почтового отчета. Это не дубликат сообщения! - person Timmy; 07.03.2017
comment
@Timmy - см. мой ответ для реализации didSelectContactProperty - person DonMag; 07.03.2017

Вы можете использовать это - хотя, если у контакта есть более одного номера телефона, это получит только первый...

var thePhoneLabel: String?
var thePhoneNumber: String?

func contactPicker(picker: CNContactPickerViewController, didSelectContact contact: CNContact) {

    picker.dismissViewControllerAnimated(true, completion: {

        if contact.phoneNumbers.count > 0 {

            if let anEntry = contact.phoneNumbers.first {
                if let theNumber = anEntry.value as? CNPhoneNumber {

                    // Get the label for the phone number (Home, Work, Mobile, etc)
                    self.thePhoneLabel = CNLabeledValue.localizedStringForLabel(anEntry.label)

                    // Get the actual phone number (as a string)
                    self.thePhoneNumber = theNumber.stringValue

                }
            }

        } else {
            // contact has no phone numbers
            self.thePhoneLabel = "(No Phone)"
            self.thePhoneNumber = "(No Phone)"
        }

    })

}

РЕДАКТИРОВАТЬ:

При использовании:

contactPickerViewController.displayedPropertyKeys = [CNContactPhoneNumbersKey]

тогда:

var theContactName: String?
var thePhoneNumber: String?
var thePhoneLabel: String?

func contactPicker(picker: CNContactPickerViewController, didSelectContactProperty contactProperty: CNContactProperty) {

    theContactName = contactProperty.contact.givenName
    thePhoneNumber = contactProperty.value?.stringValue

    if let lbl = contactProperty.label {
        thePhoneLabel = CNLabeledValue.localizedStringForLabel(lbl)
    }

}

Примечание:

func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty)

функция будет вызываться только в том случае, если у вас НЕТ

func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact)

person DonMag    schedule 06.03.2017
comment
Привет спасибо. Я уже понял, как получить первый номер: let theNumber = contactProperty.contact.phoneNumbers[0].value.stringValue Но, к сожалению, мне нужно иметь возможность получить любой конкретный номер, который выбрал пользователь, а не только 1-й номер в контакте. - person b1skit; 06.03.2017
comment
Какую функцию вы используете, чтобы позволить пользователю выбрать определенный номер телефона? - person DonMag; 06.03.2017
comment
Я показываю CNContactPickerViewController пользователю и перехватываю его возвращаемое значение, реализуя функцию протокола CNContactPickerDelegate в своем классе. Это дает мне CNContactProperty - person b1skit; 06.03.2017
comment
Смотрите мои правки в моем ответе. - person DonMag; 06.03.2017