• WKWebView使用方法


    基本使用方法


    WKWebView有两个delegate,WKUIDelegateWKNavigationDelegate。WKNavigationDelegate主要处理一些跳转、加载处理操作,WKUIDelegate主要处理JS脚本,确认框,警告框等。因此WKNavigationDelegate更加常用。

    比较常用的方法:

    #pragma mark - lifeCircle
    - (void)viewDidLoad {
        [super viewDidLoad];
        webView = [[WKWebView alloc]init];
        [self.view addSubview:webView];
        [webView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.view);
            make.right.equalTo(self.view);
            make.top.equalTo(self.view);
            make.bottom.equalTo(self.view);
        }];
        webView.UIDelegate = self;
        webView.navigationDelegate = self;
        [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
    
    }
    
    #pragma mark - WKNavigationDelegate
    // 页面开始加载时调用
    - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
    
    }
    // 当内容开始返回时调用
    - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
    
    }
    // 页面加载完成之后调用
    - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    
    }
    // 页面加载失败时调用
    - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{
    
    }
    // 接收到服务器跳转请求之后调用
    - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
    
    }
    // 在收到响应后,决定是否跳转
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    
        NSLog(@"%@",navigationResponse.response.URL.absoluteString);
        //允许跳转
        decisionHandler(WKNavigationResponsePolicyAllow);
        //不允许跳转
        //decisionHandler(WKNavigationResponsePolicyCancel);
    }
    // 在发送请求之前,决定是否跳转
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    
         NSLog(@"%@",navigationAction.request.URL.absoluteString);
        //允许跳转
        decisionHandler(WKNavigationActionPolicyAllow);
        //不允许跳转
        //decisionHandler(WKNavigationActionPolicyCancel);
    }
    #pragma mark - WKUIDelegate
    // 创建一个新的WebView
    - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
        return [[WKWebView alloc]init];
    }
    // 输入框
    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{
        completionHandler(@"http");
    }
    // 确认框
    - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{
        completionHandler(YES);
    }
    // 警告框
    - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
        NSLog(@"%@",message);
        completionHandler();
    }
    

    OC与JS交互


    WKWebview提供了API实现js交互 不需要借助JavaScriptCore或者webJavaScriptBridge。使用WKUserContentController实现js native交互。简单的说就是先注册约定好的方法,然后再调用。

    JS调用OC方法

    oc代码(有误,内存不释放):

    @interface ViewController ()<WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler>{
        WKWebView * webView;
        WKUserContentController* userContentController;
    }
    @end
    @implementation ViewController
    #pragma mark - lifeCircle
    - (void)viewDidLoad {
        [super viewDidLoad];
        //配置环境
        WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
        userContentController =[[WKUserContentController alloc]init];
        configuration.userContentController = userContentController;
        webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, 100, 100) configuration:configuration];
        //注册方法
        [userContentController addScriptMessageHandler:self  name:@"sayhello"];//注册一个name为sayhello的js方法
    
        [self.view addSubview:webView];
        [webView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.view);
            make.right.equalTo(self.view);
            make.top.equalTo(self.view);
            make.bottom.equalTo(self.view);
        }];
        webView.UIDelegate = self;
        webView.navigationDelegate = self;
        [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.test.com"]]];
    }
    - (void)dealloc{
        //这里需要注意,前面增加过的方法一定要remove掉。
        [userContentController removeScriptMessageHandlerForName:@"sayhello"];
    }
    #pragma mark - WKScriptMessageHandler
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
        NSLog(@"name:%@\\n body:%@\\n frameInfo:%@\\n",message.name,message.body,message.frameInfo);
    }
    @end
    

    上面的OC代码如果认证测试一下就会发现dealloc并不会执行,这样肯定是不行的,会造成内存泄漏。原因是[userContentController addScriptMessageHandler:self name:@"sayhello"];这句代码造成无法释放内存。(ps:试了下用weak指针还是不能释放,不知道是什么原因。)因此还需要进一步改进,正确的写法是用一个新的controller来处理,新的controller再绕用delegate绕回来。

    oc代码(正确写法):

    @interface ViewController ()<WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler>{
        WKWebView * webView;
        WKUserContentController* userContentController;
    }
    @end
    @implementation ViewController
    #pragma mark - lifeCircle
    - (void)viewDidLoad {
        [super viewDidLoad];
        //配置环境
        WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
        userContentController =[[WKUserContentController alloc]init];
        configuration.userContentController = userContentController;
        webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, 100, 100) configuration:configuration];
        //注册方法
        WKDelegateController * delegateController = [[WKDelegateController alloc]init];
        delegateController.delegate = self;
    
        [userContentController addScriptMessageHandler:delegateController  name:@"sayhello"];
    
        [self.view addSubview:webView];
        [webView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.view);
            make.right.equalTo(self.view);
            make.top.equalTo(self.view);
            make.bottom.equalTo(self.view);
        }];
        webView.UIDelegate = self;
        webView.navigationDelegate = self;
        [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.test.com"]]];
    }
    - (void)dealloc{
        //这里需要注意,前面增加过的方法一定要remove掉。
        [userContentController removeScriptMessageHandlerForName:@"sayhello"];
    }
    #pragma mark - WKScriptMessageHandler
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
        NSLog(@"name:%@\\n body:%@\\n frameInfo:%@\\n",message.name,message.body,message.frameInfo);
    }
    @end
    

    WKDelegateController代码:

    #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
    

    .m代码:

    #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
    

    h5代码:

    <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>
    

    打印出的log:

     name:sayhello
     body:{
        body = "hello world!";
    }
     frameInfo:<WKFrameInfo: 0x7f872060ce20; isMainFrame = YES; request =   <NSMutableURLRequest: 0x618000010a30> { URL: http://www.test.com/ }>
    

    注意点

    • addScriptMessageHandler要和removeScriptMessageHandlerForName配套出现,否则会造成内存泄漏。
    • h5只能传一个参数,如果需要多个参数就需要用字典或者json组装。

    oc调用JS方法

    代码如下:

    - (void)webView:(WKWebView *)tmpWebView didFinishNavigation:(WKNavigation *)navigation{
    
        //say()是JS方法名,completionHandler是异步回调block
        [webView evaluateJavaScript:@"say()" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
            NSLog(@"%@",result);
        }];
        
    }
    

    h5代码同上。

    链接:https://www.jianshu.com/p/4fa8c4eb1316

  • 相关阅读:
    二阶系统-阻尼系数
    信号反射的几个重要体现(过冲、下冲、振铃)及电路设计
    iPhone换电池是原装电池好还是换第三方大容量电池好?
    转:信号完整性:端接拓扑结构
    转:DDR中端接技术基本概念
    DDR 布线规则
    开始学习linux的一些疑问
    系统集成
    Oracle pipe
    工厂模式初识
  • 原文地址:https://www.cnblogs.com/FZP5/p/8274710.html
Copyright © 2020-2023  润新知