Osheep

时光不回头,当下最重要。

UIWebView、WKWebView之JS交互

做客户端开发,肯定避免不了JS交互,于是自己对苹果接口做了个简易封装:
JSExport–>UIWebView+Interaction、
WKScriptMessageHandler –>WKWebView+Interaction
以备以后使用。
代码非常简洁,见这里:https://github.com/V5zhou/JSInteraction.git

旧方式

旧的交互方式有通过UIWebViewDelegate实现的:JS与客户端定义好跳转页面参数,在将要跳转时捕获关键字,然后处理业务。
iOS端:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSString *urlString = [[request URL] absoluteString];
    if ([urlString isEqualToString:@"objc://loading"]) {
        if (_gotoRootViewController) {
            _gotoRootViewController();
        }
    }
    return YES;
}

JS端:

<!DOCTYPE html>
<html>
    <title>test</title>
    <meta charset="utf-8">
        <body>
            <a href="javascript:document.location = 'objc://loading'" class="btn">这是交互按钮</a>
        </body>
</html>

UIWebView+JSExport方式

导入JavaScriptCore.framework,并导入我的扩展类#import “UIWebView+Interaction.h”。

使用方式

OC调JS:

[_webView InterActionToJs:@"alertMobile('15625298071')"];

JS调OC:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    [self.webView InterActionToOc:^(InterActionOcType functionType, NSDictionary *param) {
        switch (functionType) {
            case InterActionOcType_alert:
            {
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:param[@"title"] message:param[@"content"] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
                [alert show];
            }
                break;
            case InterActionOcType_present:
            {
                self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
                Class Cls = NSClassFromString(param[@"toController"]);
                BOOL isAnimate = [param[@"animate"] boolValue];
                UIViewController *ctl = [[Cls alloc] init];
                [self presentViewController:ctl animated:isAnimate completion:nil];
            }
                break;

            default:
                break;
        }
    }];
}

添加动作

//自定义添加功能类型
typedef NS_ENUM(NSUInteger, InterActionOcType) {
    InterActionOcType_alert = 0,
    InterActionOcType_present,
    InterActionOcType_xxxxxxx,      //有啥需求就和这里添加
};

并且对应的html中添加JS,参数封装为字典形式。例:

function myPresent(ctl) {
            var param = new Array();
            param["animate"] = 1;
            param["toController"] = "SecondViewController";
            WebViewInteraction.callBack(1, param);
        }

其中callBack是通过这个JSExport实现的

@protocol WebViewJSExport <JSExport>
JSExportAs
(callBack  /** callBack 作为js方法的别名 */,
 - (void)awakeOC:(InterActionOcType)type param:(NSDictionary *)param
 );
@end

WKWebView+WKScriptMessageHandler方式

导入WebKit.framework,并导入我的扩展类#import “WKWebView+Interaction.h”。

使用方式

OC调JS:

[self.wkWebView InterActionToJs:@"JSReloadTitle('你点了刷新JS按钮,我没猜错!')"];

JS调OC:

    //注册交互类型
    [self.wkWebView registerScriptTypes:@{@"OCDismiss" : @(WKInterActionOcType_dismiss),
                                          @"OCShowAlert" : @(WKInterActionOcType_alert)}];

    [self.wkWebView InterActionToOc:^(WKInterActionOcType functionType, NSDictionary *param) {
        switch (functionType) {
            case WKInterActionOcType_dismiss:
            {
                BOOL isAnimate = [param[@"animate"] boolValue];
                [self dismissViewControllerAnimated:isAnimate completion:nil];
            }
                break;
            case WKInterActionOcType_alert:
            {
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"JS去做平方" message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
                alert.alertViewStyle = UIAlertViewStylePlainTextInput;
                [alert show];
            }
                break;
            default:
                break;
        }
    }];

添加动作

//自定义添加功能类型
typedef NS_ENUM(NSUInteger, WKInterActionOcType) {
    WKInterActionOcType_alert = 0,
    WKInterActionOcType_dismiss,
    WKInterActionOcType_xxxxxxx,      //有啥需求就和这里添加
};

并且对应的html中添加JS,参数封装为字典形式。例:

//js调oc
function myDismiss() {
   window.webkit.messageHandlers.OCDismiss.postMessage({"animate" : 1});   //这里的OCDismiss对应注册类型
}

其中callBack是通过WKScriptMessageHandler实现的

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSString *name = message.name;
        NSDictionary *value = message.body;
        WKInterActionOcType type = [self.typeDict[name] integerValue];
        if (self.block) {
            self.block(type, value);
        }
    });
}
点赞