• WKWebView 实现iOS与H5的交互<转>


    在iOS开发中,H5的嵌入可以通过UIWebView或者WKWebView。这两个都是继承UIView,来加载web数据的类。UIWebView是在iOS2的时候开始使用的。特点是加载速度慢,占用内存多,优化艰难。WKWebView是在iOS8苹果新推出的,加载速度快,占用内存较少,是一个不错的选择。如果想要比较两者的区别,您可以选择一个网页进行测试一下。鉴上所述,我们选择WKWebView进行开发。好了,废话不多说了。

    1WKWebView创建和加载

    - (void)createWebView

    {

        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]

        // 根据需要去设置对应的属性

        WKWebView *webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];

        webView.navigationDelegate = self;

        [self.view addSubview:webView];    

        NSURL *url = [NSURL URLWithString:self.strURL];

        [self loadWebViewWithURL:url];    // JS调用OC 添加处理脚本

        [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"Share"];

    }

    2

    JS调用OC代码

      [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"Share"];

    这是利用WKWebView的一个新特性MessageHandler来处理JS调用原生方法。要实现JS调用iOS原生方法,步骤见下。

    • 添加<WKScriptMessageHandler>协议。让控制器成为MessageHandler的代理对象。

    • 对于监听的方法名要和JS开发的人商量好。这里我们监听的是Share方法,对于JS开发的人员必须要以以下方式写。

     window.webkit.messageHandlers. Share.postMessage(null)

    • 实现协议方法。在这个方法里message参数有一个属性body。message.body就是JS传过来的参数,可以是字符串,可以是数组,也可以是字典。通过message.name判断可以知道监听的是JS的哪个方法。

    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message

    {    

        if ([message.name isEqualToString:@"Share"]) {

                 //TODO

        }

    }

    至此,JS调用OC代码就已完结。是不是很简单。另外,我在网上也看到了不一样的处理方式。大家可以参考WebViewJavascriptBridge我觉得写的比较清楚。本人还没有尝试过这种,如果都尝试过的宝宝能不能分享一下两者的优缺点啊。

    3

    OC调用JS代码

         [self.webView evaluateJavaScript:@"show()" completionHandler:^(id _Nullable response, NSError * _Nullable error) {

                    //TODO

          }];

    相信代码已经看得很清楚啦。show()就是JS写的方法,这个方法可传可不传参数,具体依实际情况而定。另外关于UIWebView和JS的交互,以下部分仅供参考。

        JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

        context[@"Share"] = ^() {

            NSArray *args = [JSContext currentArguments];

            dispatch_async(dispatch_get_main_queue(), ^{

                    //TODO

            });

    4

    关于<WKNavigationDelegate>

    网页加载开始,结束,失败这几个都特别简单,我就不赘述了。说一下下面这个协议方法,这个方法发生在页面跳转中。WKNavigationActionPolicy是一个枚举,WKNavigationActionPolicyAllow表示允许跳转,WKNavigationActionPolicyCancel表示取消跳转。对了,这里还有一个补充: scrollView嵌套网页和原生view,原生view要根据网页的高度来布局。我看到不少的电商应用都有这种布局,但在算高度上会有各种问题,不知道你们有遇见过?

    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler

    {

        NSString *url = navigationAction.request.URL.absoluteString;

        if(![url isEqualToString:self.strURL]) {

              // 页面跳转

        }

        decisionHandler(WKNavigationActionPolicyAllow);

    }

    5

    关于< WKUIDelegate >

    不知道您有没有遇见过JS写的alert()框在iOS上不弹出。那么您有没有实现这些协议方法呢。

    /// 创建一个新的WebView

    - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;

    /// 输入框

    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;

    /// 确认框

    - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;

    /// 警告框

    - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;

    6

     获取网页标题,网页加载进度和加载状态

    这是通过KVO的方式进行监听的。您可以点击进WKWebView的内部看一下,他们每个属性上面都有很长的解释,你不难发现这一段。举一个获取标题的例子。其他的类似。别忘了,KVO监听在dealloc中移除监听者哦。

    8E6F0A58-609E-4093-BD65-F51A10D1703D.png

        [self.webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context

    {  

        if ([keyPath isEqualToString:@"title"]) {

            if (object == self.webView) {

                if(self.navigationController) 

                    self.navigationItem.title = self.webView.title;

            }

        }

        else {

            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];

        }

    }

  • 相关阅读:
    HDU 2955 Robberies(01背包)
    HDU 2602 Bone Collector(01背包)
    HUST 1352 Repetitions of Substrings(字符串)
    HUST 1358 Uiwurerirexb jeqvad(模拟解密)
    HUST 1404 Hamming Distance(字符串)
    HDU 4520 小Q系列故事――最佳裁判(STL)
    HDU 2058 The sum problem(枚举)
    【破解】修改程序版权、添加弹窗
    HDU 1407 测试你是否和LTC水平一样高(枚举)
    HDU 1050 Moving Tables(贪心)
  • 原文地址:https://www.cnblogs.com/deng37s/p/6871913.html
Copyright © 2020-2023  润新知