Как получить URL номера телефона из строки со случайным текстом и номером телефона внутри - PullRequest
0 голосов
/ 20 июня 2019

В моем iOS-приложении у меня есть куча сообщений alertController, содержащих текст и один встроенный номер телефона, и я хотел предложить пользователю возможность совершать вызовы по alertControllerAction, и для этого мне нужно иметь возможность извлечь номер телефона из строки динамически, превратить его в URL телефонного номера и позволить старому быстрому парню делать свою работу, и вот что я сделал после того, как проследил за дюжиной туто вокруг NSDataDetector, я придумал эту функцию, которая по какой-то причине всегда возвращает ноль в моем объекте phoneNumberURL. Не могли бы вы, ребята, проверить это и сказать мне, если что-то не так?

Здесь ничего не идет:

private func showsHelpMessage() 
{

        let title = Bundle.main.localizedString(forKey: "account.help.popup.title",
                                                value: "",
                                                table: AFPConfig.sharedInstance.kLocalizableTable)

        let message = Bundle.main.localizedString(forKey: "account.help.popup.message",
                                                  value: "",
                                                  table: AFPConfig.sharedInstance.kLocalizableTable)


        var phoneNumber : String = ""
        let detectorType: NSTextCheckingResult.CheckingType = [.phoneNumber]
        do
        {
            let detector = try NSDataDetector(types: detectorType.rawValue)
            let phoneNumberDetected = detector.firstMatch(in: message, options: [], range: NSRange(location: 0, length: message.utf16.count))

            phoneNumber = (phoneNumberDetected?.phoneNumber)!
            phoneNumber = phoneNumber.removeWhitespace() // added this because i noticed the NSURL kept crashing because of the whitespaces between numbers
        }
        catch
        {
            phoneNumber = "+33969390215"
        }

        if let phoneURL = NSURL(string: ("tel://" + phoneNumber))
        {
            let alertAccessibility = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)


            alertAccessibility.addAction(UIAlertAction(title: "Appeler ?", style: .destructive, handler: { (action) in
                UIApplication.shared.open(phoneURL as URL, options: [:], completionHandler: nil)
            }))
            alertAccessibility.addAction(UIAlertAction(title: "Annuler", style: UIAlertAction.Style.cancel, handler: nil))

            self.present(alertAccessibility, animated: true, completion: nil)
        }
    }

Заранее спасибо и ура!

Ответы [ 2 ]

0 голосов
/ 20 июня 2019

Решение проблемы извлечения номеров, которые нельзя идентифицировать как определенные номера телефонов (см. Комментарий к моему другому ответу):

Вместо того, чтобы пытаться извлечь номер из сообщения и надеяться, что это телефонномер, а не расстояние или номер дома, введите заполнитель (%d) в локализованную строку и введите номер телефона в сообщение:

enum LocalPhoneNumbers {
    case reception = 1000
    case helpdesk = 4567
    // etc.
}

private function showHelpMessage() {
    // "Call the helpdesk on %d"
    let format = Bundle.main.localizedString(forKey: "account.help.popup.message",
                                              value: "",
                                              table: AFPConfig.sharedInstance.kLocalizableTable)

    let number = LocalPhoneNumbers.helpdesk.rawValue
    let message = String(format: format, number)
    let url = URL(string: "tel://\(number)")

    // Code to show alert here...

}
0 голосов
/ 20 июня 2019

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

import Foundation

enum PhoneNumberDetectionError: Error {
    case nothingDetected
    case noNumberFound
}

func extractPhoneURL(from string: String) throws -> URL? {
    let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.phoneNumber.rawValue)

    guard let detected = detector.firstMatch(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count)) else {
        throw PhoneNumberDetectionError.nothingDetected
    }

    guard let number = detected.phoneNumber else {
        throw PhoneNumberDetectionError.noNumberFound
    }

    let noWhiteSpaces = number.filter { !$0.isWhitespace }

    return URL(string: "tel://\(noWhiteSpaces)")
}

let strings = [
    "This 555–692–7753 is a phone number",
    "This 1 555 692 7753 is a phone number",
    "This 123 is an incomplete phone number",
    "This does not have a phone number",
    "This +1 555 692 7753 is a phone number",
]

strings.forEach {
    do {
        guard let url = try extractPhoneURL(from: $0) else {
            print("❌ '\($0)' failed to make URL")
            return
        }
        print("✅ '\($0)' -> \(url.absoluteString)")
    } catch {
        print("❌ '\($0)' : \(error)")
    }
}

Если вы получите ❌ за все, что, по вашему мнению, должно быть действительным, это ваша проблема.

Кроме того, у вас есть несколько странных ( ) в нескольких местах:

// Odd combination of optional unwrap and force-unwrap
phoneNumber = (phoneNumberDetected?.phoneNumber)!

// Concise equivalent
phoneNumber = phoneNumberDetected!.phoneNumber

И

// The brackets around the string concatenation don't achieve anything
if let phoneURL = NSURL(string: ("tel://" + phoneNumber))

// Better
if let phoneURL = NSURL(string: "tel://" + phoneNumber)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...