Git Product home page Git Product logo

lyswebview's Introduction

UIWebview/WKWebview原生跟JS的使用交互

iOS开发中,越来越多的使用混编的方式进行开发,就要使用webview这个控件,本文主要讲解UIWebview/WKWebview的OC跟JS的交互.

UIWebview的基本用法

UIWebview提供的方法不多.

加载页面的方法有这三个.

- (void)loadRequest:(NSURLRequest *)request;
- (void)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName baseURL:(NSURL *)baseURL;

提供的一些基本的方法有

- (void)reload;
- (void)stopLoading;

- (void)goBack;
- (void)goForward;

如果需要监听网页加载的结果.需要设置webview的delegate

__TVOS_PROHIBITED @protocol UIWebViewDelegate <NSObject>

@optional
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
- (void)webViewDidStartLoad:(UIWebView *)webView;
- (void)webViewDidFinishLoad:(UIWebView *)webView;
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;

@end

UIWebview中OC调用js

1.stringByEvaluatingJavaScriptFromString

通过stringByEvaluatingJavaScriptFromString可以让OC调用js的函数方法

NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]];
    
[self.mWebview loadRequest:request];
[webView stringByEvaluatingJavaScriptFromString:@"$(\"#logo\").hide();"];

当调用以上方法.可以直接隐藏掉百度首页的logo

2.JavaScriptCore

#pragma mark - 初始化context
+ (void)lys_Web_Set:(UIWebView *)webView {
    
    [LYSWebManager sharedManager].context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
}

#pragma mark - 调用js的方法
+ (void)lys_Web_EvaluateScript:(NSString *)script {
    
    if ([LYSWebManager sharedManager].context) {
        
        [[LYSWebManager sharedManager].context evaluateScript:script];
        
    }else {
        
        NSLog(@"不存在context对象,执行lys_Web_Set");
    }
    
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    
    /**
     初始化context
     */
    [LYSWebManager lys_Web_Set:webView];
    
    /**
     执行js脚本
     */
    [LYSWebManager lys_Web_EvaluateScript:@"$(\"#logo\").hide();"];
    
}

UIWebview中js调用OC

1.url拦截

每次url连接调转都会调用

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:

比如:

<a href=native://toast?message="我是气泡">测试</a>

H5页面点击跳转native://toast?message="我是气泡"

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    
    NSLog(@"%s",__func__);
    
    NSLog(@"请求接口:%@",request.URL);
 
    NSURL *URL = request.URL;
    if ([URL.scheme isEqualToString:@"native"]) {
        
        if ([URL.host isEqualToString:@"toast"]) {
            
            NSLog(@"toast 的参数:%@",URL.query);
            
            return NO;
        }
    }
    
    return YES;
}

通过url接口拦截到native://toast?message="我是气泡,然后解析数据

2.JavaScriptCore

js的方法映射

JSExportAs
(toast  /** handleToast 作为js方法的别名 */,
 - (void)handleToast:(NSString *)toast
 );

将js的toast方法映射为OC方法handleToast

#pragma mark - 初始化context
+ (void)lys_Web_Set:(UIWebView *)webView {
    
    [LYSWebManager sharedManager].context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
    [LYSWebManager sharedManager].context[@"native"] = [LYSWebManager sharedManager];
    
    [[LYSWebManager sharedManager].context setExceptionHandler:^(JSContext *context, JSValue *exception){
        NSLog(@"oc->js 异常: %@", exception);
    }];
}
- (void)handleToast:(NSString *)toast {
    
    NSLog(@"js->OC回调:%@",toast);
}

当H5调用

native.toast('我是气泡');

就会进入OC里面的handleToast方法

WKWebview(iOS 8+)的基本用法

WKWebview比UIWebview的优势有

  • 更多的支持HTML5的特性
  • 官方宣称的高达60fps的滚动刷新率以及内置手势
  • 将UIWebViewDelegate与UIWebView拆分成了14类与3个协议,以前很多不方便实现的功能得以实现。
  • Safari相同的JavaScript引擎
  • 占用更少的内存
  • 可以获取加载进度:estimatedProgress(UIWebView需要调用私有Api)

创建WKWebview

/*! @abstract Returns a web view initialized with a specified frame and
 configuration.
 @param frame The frame for the new web view.
 @param configuration The configuration for the new web view.
 @result An initialized web view, or nil if the object could not be
 initialized.
 @discussion This is a designated initializer. You can use
 @link -initWithFrame: @/link to initialize an instance with the default
 configuration. The initializer copies the specified configuration, so
 mutating the configuration after invoking the initializer has no effect
 on the web view.
 */
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER;

- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;

加载方法

- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;

- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macosx(10.11), ios(9.0));

- (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;

- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL API_AVAILABLE(macosx(10.11), ios(9.0));

跟UIWebview基本一致.在iOS 9新增加了两个方法

WKWebview中OC调用js

通过实现oc调用js

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    
    [webView evaluateJavaScript:@"document.getElementById(\"lcfarmlogo\").style.visibility=\"hidden\";" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        NSLog(@"%@",result);
    }];
    
    NSLog(@"%s",__func__);
    
}

当调用以上方法.可以直接隐藏掉百度首页的logo

WKWebview中js调用OC

1.url拦截

// 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    
    NSLog(@"请求接口:%@",navigationAction.request.URL);
    
    NSURL *URL = navigationAction.request.URL;
    
    /**
     url接口拦截
     */
    if ([URL.scheme isEqualToString:@"native"]) {
        
        if ([URL.host isEqualToString:@"toast"]) {
            
            NSLog(@"toast 的参数:%@",URL.query);
            
            // 不允许跳转
            decisionHandler(WKNavigationActionPolicyCancel);
            
        }
    }
    // 允许跳转
    decisionHandler(WKNavigationActionPolicyAllow);
    
}

比如:

<a href=native://toast?message="我是气泡">测试</a>

H5页面点击跳转native://toast?message="我是气泡"

通过url接口拦截到native://toast?message="我是气泡,然后解析数据

2.scriptMessageHandler

/*! @abstract Adds a script message handler.
 @param scriptMessageHandler The message handler to add.
 @param name The name of the message handler.
 @discussion Adding a scriptMessageHandler adds a function
 window.webkit.messageHandlers.<name>.postMessage(<messageBody>) for all
 frames.
 */
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;

/*! @abstract Removes a script message handler.
 @param name The name of the message handler to remove.
 */
- (void)removeScriptMessageHandlerForName:(NSString *)name;
window.webkit.messageHandlers.<name>.postMessage(<messageBody>)

创建WKWebView时,注册方法

- (WKWebView *)mWebview {
    
    if(!_mWebview){
        
        WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
        _userContentController =[[WKUserContentController alloc]init];
        configuration.userContentController = _userContentController;
        _mWebview = [[WKWebView alloc]initWithFrame:CGRectZero configuration:configuration];
        
        _mWebview.UIDelegate = self;
        _mWebview.navigationDelegate = self;
        
        //注册方法
        LYSWKWebManager * delegateController = [[LYSWKWebManager alloc]init];
        delegateController.delegate = self;
        
        [_userContentController addScriptMessageHandler:delegateController name:@"toast"];

        
    }
    return _mWebview;
    
}

配置回调方法

#import "LYSWKWebManager.h"

@implementation LYSWKWebManager

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    if ([self.delegate respondsToSelector:@selector(lysWKWeb_userContentController:didReceiveScriptMessage:)]) {
        [self.delegate lysWKWeb_userContentController:userContentController didReceiveScriptMessage:message];
    }
}

@end

H5调用以下方法就能实现js->OC的调用

window.webkit.messageHandlers.toast.postMessage({body: '我是气泡'});

总结

本文主要简单说明UIWebview和WKWebview的基本用法,OC->JS,JS->OC 的方法使用. WKWebview没有找到获取document的方法.感觉上会比UIWebview加载快速,检查内存也会比UIWebview占用少.如果已经放弃iOS 7,建议还是使用WKWebview.

本文demo

lyswebview's People

Contributors

mrliuys avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.