IOS UIWebView:如何添加DOM事件监听器?

7
如何在 UIWebView 中为 DOM 事件添加监听器?例如以下 HTML 代码:
<button type="button" id="button1">Try it</button>

在加载UIWebView中的HTML的IOS应用程序中,是否可以注册一个侦听按钮单击事件的监听器?
2个回答

9
是的,您可以通过构造URL和使用UIWebViewDelegate方法来实现此功能。
首先,在按钮标签上添加事件侦听器,可以执行以下类似的javascript代码(在页面加载后):
// In the UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if (/* when the loaded url is the target */) {
        NSString *js = @"document.getElementById('button').click = function() { window.location = 'my-protocol://dummmy.com/maybe/some/data';}";
        [webView stringByEvaluatingJavaScriptFromString: js];
    }
}

我们在按钮上绑定了一个点击事件,当它被点击时,会触发对webView的请求。
接下来我们要做的是拦截这个请求并在ObjC中执行你想要的操作。
// In the UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    if (/* when the url of the request is the crafted url */) {
        // call your objc method...
    }
}

很好的解释,谢谢!顺便问一下,'window.location'是什么?看起来像DOM根节点,是吗?我能直接使用'window.location'来操作DOM吗? - Anton Ashanin
您可以直接使用传递到“stringByEvaluatingJavaScriptFromString”方法中的“js”变量来操作DOM。例如,删除页面内容:“document.write('');”。 - Egist Li
如果IOS正在寻找的DOM节点需要一些时间才能被React/Vue等客户端库渲染,那么这个过程会失败吗? - timebandit
@EgistLi 如果IOS正在寻找的DOM节点需要等待一些毫秒才能被React/Vue等客户端库渲染,那么这个操作失败的风险是否存在? - timebandit
@timebandit 我认为是这样的。如果你正在使用React/Vue内部的某些东西,你需要以某种方式钩入React/Vue的生命周期。或者,如果按钮的onClick事件监听器的事件传播没有停止,你可以尝试使用事件委托并在document对象上绑定按钮的onclick事件监听器。 - Egist Li

1
这里是在UIWebView中拦截链接被点击的Swift方法:
首先,需要创建一个代理对象:
class ViewController: UIViewController, UIWebViewDelegate { //... }

并将其分配:
override func viewDidLoad() {
        super.viewDidLoad()

        webView.delegate = self

        //...
}

现在我们可以使用它来拦截:
    func webViewDidFinishLoad(_ webView: UIWebView) {
            if (currentURL?.lowercased().range(of:"some/url") != nil) {
                webView.stringByEvaluatingJavaScript(from: "document.getElementsByTagName('a')[0].onclick = function() {window.location = 'injected://loadPDF1'; return false;}")
            }
    }

    // Sent before a web view begins loading a frame.
    func webView(_: UIWebView, shouldStartLoadWith: URLRequest, navigationType: UIWebViewNavigationType) -> Bool{
        // intercept all injected page calls
        if (shouldStartLoadWith.url?.scheme == "injected") {
            return false;
        }
        return true;
    }

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