美文网首页
IOS WKWebView 和JS交互

IOS WKWebView 和JS交互

作者: 透支未来 | 来源:发表于2017-09-27 09:04 被阅读371次
    #import <UIKit/UIKit.h>
    
    @interface WKWebViewController : UIViewController
    
    @end
    
    
    #import "WKWebViewController.h"
    #import <WebKit/WebKit.h>
    #import "WKDelegateController.h"
    
    @interface WKWebViewController ()<WKDelegate,WKScriptMessageHandler,WKUIDelegate,WKNavigationDelegate>
    @property(strong,nonatomic)WKWebView* webView;
    @property(strong,nonatomic)WKUserContentController* userContentController;
    @end
    
    @implementation WKWebViewController
    
    
    -(instancetype)init
    {
        if(self = [super init])
        {
        }
        return self;
        
    }
    -(void)viewDidDisappear:(BOOL)animated
    {
        [super viewDidDisappear:animated];
        [_webView removeObserver:self forKeyPath:@"loading" context:nil];//移除kvo
        [_webView removeObserver:self forKeyPath:@"title" context:nil];
        [_webView removeObserver:self forKeyPath:@"estimatedProgress" context:nil];
        
    }
    -(void)addKVO
    {
        [self.webView addObserver:self
                       forKeyPath:@"loading"
                          options:NSKeyValueObservingOptionNew
                          context:nil];
        
        [self.webView addObserver:self
                       forKeyPath:@"title"
                          options:NSKeyValueObservingOptionNew
                          context:nil];
        
        [self.webView addObserver:self
                       forKeyPath:@"estimatedProgress"
                          options:NSKeyValueObservingOptionNew
                          context:nil];
        
    }
    - (void)observeValueForKeyPath:(NSString *)keyPath
                          ofObject:(id)object
                            change:(NSDictionary<NSString *,id> *)change
                           context:(void *)context
    {
        if ([keyPath isEqualToString:@"loading"])
        {
            NSLog(@"loading");
            
        } else if ([keyPath isEqualToString:@"title"])
        {
            self.title = self.webView.title;
        } else if ([keyPath isEqualToString:@"estimatedProgress"])
        {
            NSLog(@"progress: %f", self.webView.estimatedProgress);
        }
        // 加载完成
        if (!self.webView.loading)
        {
        }
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //初始化一个WKWebViewConfiguration对象
        WKWebViewConfiguration *config = [WKWebViewConfiguration new];
        //初始化偏好设置属性:preferences
        config.preferences = [WKPreferences new];
        //The minimum font size in points default is 0;
        config.preferences.minimumFontSize = 10;
        //是否支持JavaScript
        config.preferences.javaScriptEnabled = YES;
        //不通过用户交互,是否可以打开窗口
        config.preferences.javaScriptCanOpenWindowsAutomatically = NO;
        
        self.userContentController =[[WKUserContentController alloc]init];
        config.userContentController = self.userContentController;
    
        //注册方法
        WKDelegateController * delegateController = [[WKDelegateController alloc]init];
        delegateController.delegate = self;
    
        [self.userContentController addScriptMessageHandler:delegateController  name:@"sayhello"];
    
        self.webView = [[WKWebView alloc]initWithFrame:self.view.frame configuration:config];
        self.webView.UIDelegate = self;
        self.webView.navigationDelegate = self;
    //    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];
        [self.view addSubview:self.webView];
        
        NSString* path = [[NSBundle mainBundle] pathForResource:@"b" ofType:@"html"];
        NSURL* url = [NSURL fileURLWithPath:path];
        NSURLRequest* request = [NSURLRequest requestWithURL:url] ;
        [self.webView loadRequest:request];
        [self addKVO];
        //[request addValue:[self readCurrentCookieWithDomain:@"http://www.test.com/"] forHTTPHeaderField:@"Cookie"];
    }
    
    
    #pragma mark --WKScriptMessageHandler
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
    {
        if ([message.name isEqualToString:@"sayhello"]) {
            // 打印所传过来的参数,只支持NSNumber, NSString, NSDate, NSArray,
            // NSDictionary, and NSNull类型
            //do something
            NSLog(@"%@", message.body);
        }
    }
    
    - (NSString *)readCurrentCookieWithDomain:(NSString *)domainStr{
        NSHTTPCookieStorage*cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
        NSMutableString * cookieString = [[NSMutableString alloc]init];
        for (NSHTTPCookie*cookie in [cookieJar cookies]) {
            [cookieString appendFormat:@"%@=%@;",cookie.name,cookie.value];
        }
        
        //删除最后一个“;”
        [cookieString deleteCharactersInRange:NSMakeRange(cookieString.length - 1, 1)];
        return cookieString;
    }
    
    
    
    #pragma mark ---WKUIDelegate
    // 创建新的webview
    // 可以指定配置对象、导航动作对象、window特性
    - (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
    {
        return self.webView;
    }
    
    // webview关闭时回调
    - (void)webViewDidClose:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0){
        
    }
    
    // 调用JS的alert()方法
    -(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"警告" message:@"调用alert提示框" preferredStyle:UIAlertControllerStyleAlert];
        [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            completionHandler();
        }]];
        [self presentViewController:alert animated:YES completion:nil];
        NSLog(@"alert message:%@",message);
    }
    
    // 调用JS的confirm()方法
    - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler
    {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"确认框" message:@"调用confirm提示框" preferredStyle:UIAlertControllerStyleAlert];
        [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            completionHandler(YES);
        }]];
        [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            completionHandler(NO);
        }]];
        [self presentViewController:alert animated:YES completion:NULL];
        NSLog(@"confirm message:%@", message);
    }
    
    // 调用JS的prompt()方法
    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"输入框" message:@"调用输入框" preferredStyle:UIAlertControllerStyleAlert];
        [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
            textField.textColor = [UIColor blackColor];
        }];
        [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            completionHandler([[alert.textFields lastObject] text]);
        }]];
        
        [self presentViewController:alert animated:YES completion:NULL];
        
    }
    
    
    #pragma mark ---WKNavigationDelegate
    //开始加载时调用
    -(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
        
    }
    //当内容开始返回时调用
    -(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
        
    }
    //页面加载完成之后调用
    - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
        
        //取出cookie
    //    NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    //    //js函数
    //    NSString *JSFuncString =
    //    @"function setCookie(name,value,expires)\
    //    {\
    //    var oDate=new Date();\
    //    oDate.setDate(oDate.getDate()+expires);\
    //    document.cookie=name+'='+value+';expires='+oDate+';path=/'\
    //    }\
    //    function getCookie(name)\
    //    {\
    //    var arr = document.cookie.match(new RegExp('(^| )'+name+'=({FNXX==XXFN}*)(;|$)'));\
    //    if(arr != null) return unescape(arr[2]); return null;\
    //    }\
    //    function delCookie(name)\
    //    {\
    //    var exp = new Date();\
    //    exp.setTime(exp.getTime() - 1);\
    //    var cval=getCookie(name);\
    //    if(cval!=null) document.cookie= name + '='+cval+';expires='+exp.toGMTString();\
    //    }";
    //
    //    //拼凑js字符串
    //    NSMutableString *JSCookieString = JSFuncString.mutableCopy;
    //    for (NSHTTPCookie *cookie in cookieStorage.cookies) {
    //        NSString *excuteJSString = [NSString stringWithFormat:@"setCookie('%@', '%@', 1);", cookie.name, cookie.value];
    //        [JSCookieString appendString:excuteJSString];
    //    }
    //    //执行js
    //    [webView evaluateJavaScript:JSCookieString completionHandler:nil];
    //
    //    //say()是JS方法名,completionHandler是异步回调block
    //    [self.webView evaluateJavaScript:@"say()" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
    //        NSLog(@"%@",result);
    //    }];
        
    }
    // 页面加载失败时调用
    - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation
    {
        NSLog(@"didFailProvisionalNavigation");
    }
    // 接收到服务器跳转请求之后调用
    - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
        NSLog(@"didReceiveServerRedirectForProvisionalNavigation");
    
    }
    // 在收到响应后,决定是否跳转
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
        NSLog(@"decidePolicyForNavigationResponse");
        
        decisionHandler( WKNavigationResponsePolicyAllow);
    
    }
    // 在发送请求之前,决定是否跳转
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
        NSLog(@"decidePolicyForNavigationAction");
        
        decisionHandler(WKNavigationActionPolicyAllow);
        
    
    }
    
    
    - (void)dealloc{
        //这里需要注意,前面增加过的方法一定要remove掉。
        [self.userContentController removeScriptMessageHandlerForName:@"sayhello"];
    }
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    /*
    #pragma mark - Navigation
    
    // In a storyboard-based application, you will often want to do a little preparation before navigation
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */
    
    @end
    
    
    #import <UIKit/UIKit.h>
    #import <WebKit/WebKit.h>
    @protocol WKDelegate <NSObject>
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
    @end
    
    @interface WKDelegateController : UIViewController <WKScriptMessageHandler>
    @property (weak , nonatomic) id<WKDelegate> delegate;
    @end
    
    
    
    
    
    
    #import "WKDelegateController.h"
    
    @interface WKDelegateController ()
    
    @end
    
    @implementation WKDelegateController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    }
    
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
        if ([self.delegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) {
            [self.delegate userContentController:userContentController didReceiveScriptMessage:message];
        }
    }
    
    @end
    
    
    
    

    js代码

    <html>
    <head>
        <script>
    function say()
    {
    //前端需要用 window.webkit.messageHandlers.注册的方法名.postMessage({body:传输的数据} 来给native发送消息
        window.webkit.messageHandlers.sayhello.postMessage({body: 'hello world!'});
    }
    </script>
    </head>
        <body>
            <h1>hello world</h1>
            <button onclick="say()">say hello</button>
        </body>
    
    </html>
    
    
    <html>
      <head>
        <title>iOS and Js</title>
        <style type="text/css">
          * {
            font-size: 40px;
          }
        </style>
      </head>
      
      <body>
        
        <div style="margin-top: 100px">
          <h1>Test how to use objective-c call js</h1><br/>
          <div><input type="button" value="call js alert" onclick="callJsAlert()"></div>
          <br/>
          <div><input type="button" value="Call js confirm" onclick="callJsConfirm()"></div><br/>
        </div>
        <br/>
        <div>
          <div><input type="button" value="Call Js prompt " onclick="callJsInput()"></div><br/>
          <div>Click me here: <a href="http://www.baidu.com">Jump to Baidu</a></div>
        </div>
        
        <br/>
        <div id="SwiftDiv">
          <span id="jsParamFuncSpan" style="color: red; font-size: 50px;"></span>
        </div>
        
        <script type="text/javascript">
          function callJsAlert() {
            alert('Objective-C call js to show alert');
            
            window.webkit.messageHandlers.AppModel.postMessage({body: 'call js alert in js'});
          }
        
        function callJsConfirm() {
          if (confirm('confirm', 'Objective-C call js to show confirm')) {
            document.getElementById('jsParamFuncSpan').innerHTML
            = 'true';
          } else {
            document.getElementById('jsParamFuncSpan').innerHTML
            = 'false';
          }
          
          // AppModel是我们所注入的对象
          window.webkit.messageHandlers.AppModel.postMessage({body: 'call js confirm in js'});
        }
        
        function callJsInput() {
          var response = prompt('Hello', 'Please input your name:');
          document.getElementById('jsParamFuncSpan').innerHTML = response;
          
           // AppModel是我们所注入的对象
          window.webkit.messageHandlers.AppModel.postMessage({body: response});
        }
       </script>
      </body>
    </html>
    
    

    相关文章

      网友评论

          本文标题:IOS WKWebView 和JS交互

          本文链接:https://www.haomeiwen.com/subject/czuyextx.html