Phone 无法使用 openURL 打开使用 NSDataDetector 检测到的数字

Phone numbers detected using NSDataDetector could not be opened using openURL

好的,我使用 NSDataDetector 检测 phone 个数字,如下所示:

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: [=11=].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

我是否应该对该号码进行任何操作才能使用它拨打电话?

删除 space,这应该有效: +48576-786-987

作为, space 是 phone 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 属性,它是在检测到 phone 个数字时设置的。所以 您可以将代码稍微简化为

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 { [=11=].phoneNumber }
    }
}

NSDataDetector(types:) 只能因无效类型而失败,这将是 编程错误。因此这里可以接受强制尝试。