WKWebView:HTML内容中的mailto链接无法打开邮件应用程序

14

我创建了一个非常简单的iOS应用程序(Swift 5)。它只是一个WKWebView,加载我的PWA网址。

除了所有的<a href="mailto:name@name.com">Mail me</a>链接都无法正常工作。当我点击它们时,什么也不会发生,我的邮件应用程序不会打开。

这是我ViewController.swift的代码:

//
//  ViewController.swift
//  panel
//
//  Created by kevin on 25/07/2019.
//  Copyright © 2019 umono. All rights reserved.
//

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate {
    
    var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let myURL = URL(string:"https://someUrlToMyApp.appspot.com")
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
        
        if #available(iOS 11.0, *) {
            webView.scrollView.contentInsetAdjustmentBehavior = .never;
        }
        
    }
    
    override func loadView() {
        
        let webConfiguration = WKWebViewConfiguration()
        webConfiguration.dataDetectorTypes = [.all]
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        view = webView
        
    }

}

编辑:

谢谢大家,以下是我的可用代码:

//
//  ViewController.swift
//  panel
//
//  Created by kevin on 25/07/2019.
//  Copyright © 2019 umono. All rights reserved.
//

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate {
    
    var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let myURL = URL(string:"https://someUrlToMyApp.appspot.com")
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
        
        if #available(iOS 11.0, *) {
            webView.scrollView.contentInsetAdjustmentBehavior = .never;
        }
        
        webView.navigationDelegate = self
        
    }
    
    override func loadView() {
        
        let webConfiguration = WKWebViewConfiguration()
        webConfiguration.dataDetectorTypes = [.all]
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        view = webView
        
    }

}

extension ViewController: WKNavigationDelegate {
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
                 decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        guard
            let url = navigationAction.request.url else {
                decisionHandler(.cancel)
                return
        }
        
        let string = url.absoluteString
        if (string.contains("mailto:")) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
            decisionHandler(.cancel)

            return
        }
        decisionHandler(.allow)
    }
}

设备设置中是否已设置邮件? - TheTiger
它在Safari中运行正常(它打开了我的电子邮件应用程序)。 - kevinius
也许这是相同的问题 https://dev59.com/el8d5IYBdhLWcg3wvkON - m1sh0
我尝试了那篇帖子中提供的所有解决方案,但都没有起作用... - kevinius
@TheTiger,正如您在我的代码中所看到的,我已经设置了:webConfiguration.dataDetectorTypes = [.all]。 - kevinius
显示剩余5条评论
1个回答

16

实现WKNavigationDelegate是实现您想要的方式之一:

import UIKit
import WebKit

class ViewController: UIViewController {

    @IBOutlet weak var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        guard
            let file = Bundle.main.path(forResource: "test", ofType: "html"),
            let html = try? String(contentsOfFile: file) else {
                return
        }

        webView.navigationDelegate = self
        webView.loadHTMLString(html, baseURL: nil)
    }

    @IBAction func didTapButton(_ sender: Any) {
        let email = "email@email.com"
        guard
            let url = URL(string: "mailto:\(email)") else {
                return
        }

        UIApplication.shared.open(url, options: [:], completionHandler: nil)
    }
}

extension ViewController: WKNavigationDelegate {
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
                 decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        guard
            let url = navigationAction.request.url,
            let scheme = url.scheme else {
                decisionHandler(.cancel)
                return
        }

        if (scheme.lowercased() == "mailto") {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
            // here I decide to .cancel, do as you wish
            decisionHandler(.cancel)
            return
        }
        decisionHandler(.allow)
    }
}

这里有一个ViewController,它有一个名叫webView的outlet,这个WKWebView将会加载一个像这样的html文件:

<a href="mailto:email@email.com">Mail me</a>

我还在Storyboard中添加了一个按钮,仅用于参考,该按钮将具有上述描述的IBAction didTapButton

关键是:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
                 decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)

该代码将为您提供URL,并让您决定适合它的策略。在此,我检查是否包含mailto:,因为我已经知道这是您感兴趣的内容,所以如果包含,则会像在屏幕上按下UIButton 按钮时那样简单地打开URL。

希望对您有所帮助,祝好!

附:请确保在真实设备上运行(模拟器中没有安装邮件应用程序),还要确保您已安装邮件应用程序,因为我没有安装...


2
@kevinius,你是否设置了webView.navigationDelegate = self - TheTiger
1
更新了我的原始帖子,包括完整的可工作解决方案。 - kevinius
2
但是,如果您的URL字符串中包含mailto字符串,则此方法将失败。例如:https://abcmailto.com,根据条件它将在应用程序外部打开。因此,最好匹配url.scheme而不是使用contains函数。 - TheTiger
如果您正在使用JavaScript函数进行日志记录和条件主题和正文的构建,然后调用window.open(``mailto:email@email.com?subject=$ {subject}&body=$ {body}``,'_blank');,则似乎不会触发委托方法。 - jhelzer
我发现这是一个半优雅的解决方案,所以我不必修改所有的Web代码来使用适用的hrefs:https://blog.nextzy.me/ios-handling-popup-new-window-inside-web-view-c9c91b23ac2b - jhelzer
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接