• H5与iOS交互


    H5页面与原生交互项目中经常遇到,今天做个小结。

    从iOS原生的角度讲,我们可以使用UIWebViewWKWebView组件来展示H5页面,那么两者有什么区别呢?

    讲述UIWebView只是让大家了解下这个历史,按现在的情况我们主要使用WKWebView

    一、推出时间

    UIWebView从iOS2.0推出到iOS12.0废弃,WKWebView从iOS8.0推出

    UIWebView ios(2.0, 12.0)  、WKWebView ios(8.0)

    UIWebView 

    UIKIT_EXTERN API_DEPRECATED("No longer supported; please adopt WKWebView.", ios(2.0, 12.0)) API_UNAVAILABLE(tvos, macos) @interface UIWebView : UIView <NSCoding, UIScrollViewDelegate>

    WKWebView

    #if TARGET_OS_IPHONE
    WK_EXTERN API_AVAILABLE(macos(10.10), ios(8.0))
    @interface WKWebView : UIView
    #else
    WK_EXTERN API_AVAILABLE(macos(10.10), ios(8.0))
    @interface WKWebView : NSView
    #endif

    二、性能对比

    UIWebView

    占用过多内存,且内存峰值更是夸张。说白了就是性能低

    WKWebView

    1、网页加载速度快,内存消耗低。

    2、更多的支持HTML5的特性,

    3、高达60fps的滚动刷新率以及内置手势,

    4、Safari相同的JavaScript引擎(但就这一点性能完胜),

    5、增加了进度属性estimatedProgress等特性

    三、交互

    UIWebView

    1、OC调用JS

    - (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

    2、JS调用OC

    <1>iOS原生拦截URL

    拦截到指定URL做响应操作

    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType API_DEPRECATED("No longer supported.", ios(2.0, 12.0));

    <2>使用JavaScriptCore实现(要注意循环引用的问题)

    JSDelegate
    #import <Foundation/Foundation.h>
    #import <JavaScriptCore/JavaScriptCore.h>
    
    /**
     *  H5会通过对象Bridge调用协议中的方法
     */
    @protocol JSDelegate <JSExport>
    
    
    // 关闭页面
    - (void)finishPage;
    
    
    @end
    JSObject(中间对象,解决循环引用的问题,不直接让WebViewController遵守JSDelegate的原因)
    #import <Foundation/Foundation.h>
    #import "JSDelegate.h"
    #import "WebViewController.h"
    
    @interface JSObject : NSObject <JSDelegate>
    
    @property(nonatomic, weak) WebViewController *h5VC;
    
    @end
    - (void)finishPage {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.h5VC pop];
            });
    }
    WebViewController
    @property (strong, nonatomic) JSContext *jsContext;
    // 获取JSContext,并注入对象
    - (void)creatJscontext
    {
        //  获取js上下文(JSContext)
        self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        // 遵守JSExport协议的对象(符合JSExport的对象都将转换为JavaScript包装器对象
        JSObject *obj = [[JSObject alloc] init];
        obj.h5VC = self;
        //  注入交互对象Bridge,H5通过Bridge对象调用JSExport中的方法
        self.jsContext[@"Bridge"] = obj;
    }

    H5端将通过Bridge.finishPage()调用原生方法

    备注:

    JSContext
    /*!
    @interface
    @discussion A JSContext is a JavaScript execution environment. All
     JavaScript execution takes place within a context, and all JavaScript values
     are tied to a context.
    */
    JS_EXPORT API_AVAILABLE(macos(10.9), ios(7.0))
    @interface JSContext : NSObject

    UIWebView什么时机创建JSContext环境

    什么时候UIWebView会创建JSContext环境,分两种方式,

    第一在渲染网页时遇到<script标签时,就会创建JSContext环境去运行JavaScript代码

    第二就是使用方法[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]去获取JSContext环境时,

    这时无论是否遇到<script标签,都会去创造出来一个JSContext环境,而且和遇到<script标签再创造环境是同一个。

    JSExport
     All objects that conform to JSExport convert to JavaScript wrapper objects,
     even if they subclass classes that would otherwise behave differently. For
     example, if a subclass of NSString conforms to JSExport, it converts to
     JavaScript as a wrapper object rather than a JavaScript string.
    */
    @protocol JSExport
     
    WKWebView
    1、OC调用JS
    /* @abstract Evaluates the given JavaScript string.
     @param javaScriptString The JavaScript string to evaluate.
     @param completionHandler A block to invoke when script evaluation completes or fails.
     @discussion The completionHandler is passed the result of the script evaluation or an error.
    */
    - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;

    2、JS调用OC

    <1>iOS原生拦截URL

    /*! @abstract Decides whether to allow or cancel a navigation.
     @param webView The web view invoking the delegate method.
     @param navigationAction Descriptive information about the action
     triggering the navigation request.
     @param decisionHandler The decision handler to call to allow or cancel the
     navigation. The argument is one of the constants of the enumerated type WKNavigationActionPolicy.
     @discussion If you do not implement this method, the web view will load the request or, if appropriate, forward it to another application.
     */
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

    <2>使用MessageHandler(WKScriptMessageHandler)实现

    WKWebView 初始化时,有一个参数叫configuration

    它是WKWebViewConfiguration类型的参数,而WKWebViewConfiguration有一个属性叫userContentController

    它又是WKUserContentController类型的参数。

    WKUserContentController对象有一个方法- addScriptMessageHandler:name:,我把这个功能简称为MessageHandler。

    添加或者删除消息处理

    /*! @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;

    收到H5发送的消息

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @class WKScriptMessage;
    @class WKUserContentController;
    
    /*! A class conforming to the WKScriptMessageHandler protocol provides a
     method for receiving messages from JavaScript running in a webpage.
     */
    @protocol WKScriptMessageHandler <NSObject>
    
    @required
    
    /*! @abstract Invoked when a script message is received from a webpage.
     @param userContentController The user content controller invoking the
     delegate method.
     @param message The script message received.
     */
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
    
    @end

    H5端调用

    window.webkit.messageHandlers.<name>.postMessage(<messageBody>)

    综上所述:

    最优的方案就是使用WKWebView,交互使用MessageHandler

     参考:

    https://www.jianshu.com/p/94bd66874dba

    https://www.jianshu.com/p/939db6215436

    https://www.jianshu.com/p/f896d73c670a

    https://blog.csdn.net/lyyo_cd/article/details/84304864

    https://www.jianshu.com/p/79e329ff8953

    https://blog.csdn.net/u011619283/article/details/52135988

  • 相关阅读:
    ValueError: Layer conv2d_1 was called with an input that isn't a symbolic tensor. Received type: <class 'tuple'>. Full input: [(600, 600, 3)]. All inputs to the layer should be tensors.
    OSError: `pydot` failed to call GraphViz.Please install GraphViz (https://www.graphviz.org/) and ensure that its executables are in the $PATH.该错误的解决
    numpy操作1--任务一:单通道图像转三通道理解/任务二:按axis=0或axis=1或axis=2(轴)堆叠(stack)
    探究灰度图像对目标检测测试结果影响----RGB转灰度图像、灰度图像扩充成三通道
    git项目上传github
    jupyter中,ipynb文件转pdf文件
    面试-操作系统
    数据库-面试
    面试—计算机网络
    PE文件结构
  • 原文地址:https://www.cnblogs.com/lijianyi/p/14581030.html
Copyright © 2020-2023  润新知