2

如果 (stringToURL?.isValidURL)! <--当在 Guard 语句中安全声明时,不确定为什么编译器需要在stringToURL上进行可选链接。此外,isValidURL 的字符串扩展名:Bool始终返回 Bool 但编译器仍希望展开。

在这个例子中,annotation.subtitle应该已经是 URL 格式的字符串,但我想确认一下。

尝试使用在 guard 中定义的变量变得比预期的更复杂,因为需要进一步展开。现在我觉得我让几行代码过于复杂,难以理解/阅读我的实现。

func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
    let backupURL = URL(string: "https://www.google.com")!
    guard let currentAnnotation = view.annotation, var stringToURL = currentAnnotation.subtitle else {
        // currentAnnotation has blank subtitle.  Handle by opening up any website.
        UIApplication.shared.open(backupURL, options: [:])
        return
    }
    if (stringToURL?.isValidURL)!{
        stringToURL = stringToURL?.prependHTTPifNeeded()
        if let url = URL(string: stringToURL!){
            UIApplication.shared.open(url, options: [:])
        } else {
            UIApplication.shared.open(backupURL, options: [:])
        }
    }
}

extension String {
var isValidURL: Bool {
    let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
    if let match = detector.firstMatch(in: self, options: [], range: NSRange(location: 0, length: self.endIndex.encodedOffset)) {
        // it is a link, if the match covers the whole string
        return match.range.length == self.endIndex.encodedOffset
    } else {
        return false
    }
}

func prependHTTPifNeeded()-> String{
    let first4 = self.prefix(4)
    if first4 != "http" {
        return "http://" + self
    } else {
        return self
    }
}

}

代码块正确执行。
annotation.subtitle = " https://www.yahoo.com " <--- 雅虎打开

annotation.subtitle = "www.yahoo.com" <--- 雅虎打开

annotation.subtitle = "yahoo" <--- google.com 打开,因为我们没有有效的 URL 字符串

4

1 回答 1

1

问题在于它currentAnnotation.subtitle是 a String??,因为subtitle它不仅是 a String?,它本身也是MKAnnotation协议的一个可选属性。所以一个简单的 unwrap 只验证可选协议subtitle是否被实现,而不是结果String?是 not nil。你也必须打开它。

但是你可以这样做guard var stringToURL = view.annotation?.subtitle as? String else { ... },它会被正确地展开为String

func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
    let backupURL = URL(string: "https://www.google.com”)!

    guard var stringToURL = view.annotation?.subtitle as? String else {
        UIApplication.shared.open(backupURL)
        return
    }

    if stringToURL.isValidURL {
        stringToURL = stringToURL.prependHTTPifNeeded()
        let url = URL(string: stringToURL) ?? backupURL
        UIApplication.shared.open(url)
    }
}

注意,如果没有提供字符串,这将打开backupURL,但如果提供了一个字符串并且不是有效的 URL,它不会做任何事情。因此,也许您的意思是以下内容,backupURL如果无法打开,它将打开stringToURL

func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
    let backupURL = URL(string: "https://www.google.com")!

    guard var stringToURL = view.annotation?.subtitle as? String,
        stringToURL.isValidURL else {
            UIApplication.shared.open(backupURL)
            return
    }

    stringToURL = stringToURL.prependHTTPifNeeded()
    let url = URL(string: stringToURL) ?? backupURL
    UIApplication.shared.open(url)
}

在哪里:

extension String {
    var isValidURL: Bool {
        let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
        let range = NSRange(startIndex..., in: self)
        return detector.firstMatch(in: self, range: range)?.range == range
    }

    func prependHTTPifNeeded() -> String{
        if prefix(4) != "http" {
            return "http://" + self
        } else {
            return self
        }
    }
}
于 2019-02-08T17:43:01.970 回答