WKUserContentController:后续添加/删除/添加脚本消息处理程序导致处理程序无法从JavaScript调用

时间:2016-07-13 16:11:50

标签: javascript ios webkit wkwebview

TL;博士

DO

WKUserContentController* ucc = self.webView.configuration.userContentController;
[ucc addScriptMessageHandler:self name:@"serverTimeCallbackHandler"]; // add
[ucc removeScriptMessageHandlerForName:@"serverTimeCallbackHandler"]; // remove
[ucc addScriptMessageHandler:self name:@"serverTimeCallbackHandler"]; // add

...并且不会从JavaScript调用window.webkit.messageHandlers.serverTimeCallbackHandler.postMessage(<messageBody>)

描述

我在使用WebKit.framework时遇到了问题。这要么是框架的错误,要么是对它的不当使用。

我有一个与网页互动的.js文件。在交互结束时,脚本会调用window.webkit.messageHandlers.<name>.postMessage(<messageBody>)

(function() {
    var timeZoneCoockieName = 'cTz';

    function getServerTimeWithTimeZone() {
        PageMethods.GetServerTime(function(time) {
            var serverTime = time;

            var timezone = getCookie(timeZoneCoockieName);

            var message = {'time': serverTime, 'timezone': timezone}; 

            window.webkit.messageHandlers.serverTimeCallbackHandler.postMessage(message);
        });
    }

    function getCookie(name) {
        var value = "; " + document.cookie;
        var parts = value.split("; " + name + "=");
        if (parts.length == 2) return parts.pop().split(";").shift();
    }

    getServerTimeWithTimeZone();
})();

基本上,脚本调用页面方法,从服务器检索时间并在回调时查找存储在cookie中的时区。

本机组件旨在包装此调用并公开方便的API以检索日期/时区信息。

- (void)getServerTimeWithCompletion:((^)(id, NSError *))completion {
    // Adding same message handler twice, leads to an exception.
    // Removing message handler with the same name, just in case.
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"serverTimeCallbackHandler"];
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"serverTimeCallbackHandler"];

    self.getServerTimeCompleteBlock = completion;

    NSString * jsPath = [[NSBundle mainBundle] pathForResource:@"GetServerTime" ofType:@"js"];
    if (![jsPath isBlank]) {
        NSError* encodingError = nil;
        NSString* jsContent = [NSString stringWithContentsOfFile:jsPath
                                                        encoding:NSUTF8StringEncoding
                                                           error:&encodingError];
        if (!encodingError) {
            [self.webView evaluateJavaScript:jsContent completionHandler:  ^(id _Nullable result, NSError * _Nullable evalError) {
                if (evalError) {
                    if (completion) { completion(nil, evalError); }
                }
             }];
        } else {
            if (completion) { completion(nil, encodingError); }
        }
    }
    else {
        if (completion) { completion(nil, nil); }
    }
}

现在,如果用户调用此方法两次,则第二次不从JavaScript调用处理程序。

Web调试器附加到应用程序的Web视图,记录错误:

InvalidAccessError: DOM Exception 15: A parameter or an operation was not supported by the underlying object.

web debugger screenshot

0 个答案:

没有答案