Телефонные номера, обнаруженные с помощью NSDataDetector, не могут быть открыты с помощью openURL

Хорошо я пользуюсь NSDataDetector для определения телефонных номеров, как это:

func matchesFor(type: NSTextCheckingResult.CheckingType) -> [String] {

    do {

        let nsstring = self as NSString
        let detector = try NSDataDetector(types: type.rawValue)
        let matches = detector.matches(in: self, options: [], range: NSRange(location: 0, length: nsstring.length))

        return matches.map { nsstring.substring(with: $0.range) }

    } catch {
        return []
    }
}

и он находит цифры. Но затем я пытаюсь открыть эти цифры следующим образом:

func makeACall(phoneNumber: String) {

    if let url = URL(string: "tel://\(phoneNumber)"), UIApplication.shared.canOpenURL(url) {
        UIApplication.shared.openURL(url)
    }
}

и это не работает. Зачем?

Пример, который я имею в виду:

+48 576-786-987

Должен ли я что-то сделать с этим номером, чтобы использовать его для звонка?

2 ответа

Решение

Уберите пробел, это должно работать: +48576-786-987

Как сказал Юнь Чэнь, пробел - недопустимый символ в URL-адресе телефона.

Если вы используете URLComponents() вместо URL(string:) тогда все символы автоматически экранируются при необходимости. Пример:

let phoneNumber = "+48 576-786-987"

var urlcomps = URLComponents()
urlcomps.scheme = "tel"
urlcomps.host = phoneNumber

if let url = urlcomps.url, UIApplication.shared.canOpenURL(url) {
    print("Calling:", url.absoluteString) // Calling: tel://+48%20576-786-987
    UIApplication.shared.openURL(url)
}

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

extension String {
    func phoneNumbers() -> [String] {

        let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.phoneNumber.rawValue)
        let matches = detector.matches(in: self, range: NSRange(location: 0, length: utf16.count))
        return matches.flatMap { $0.phoneNumber }
    }
}

NSDataDetector(types:) может произойти сбой только для недопустимого типа, что может быть ошибкой программирования. Поэтому принудительная попытка здесь приемлема.

Другие вопросы по тегам