zoukankan      html  css  js  c++  java
  • Weex 解析(二)—— NativeBridge

      (本篇幅主要讲解Weex 中iOS native与js交互实现)

    大纲:

    • weex 总框架预览
    • iOS NativeBridge总设计原理

     一、weex 总框架预览

       在写NativeBridge 总设计之前必须先了解下Weex总体部署图,这张图来自于网上,如下:

                          图1.0  weex 总设计图 

         从上图可以看出weex总体流程如下:

       Service:

    1. 开发人员,开发weex 文件(如:helloweex.we)。
    2. 通过transformer引擎将weex文件大包成相应的js文件。

     Client:

    1. 在应用启动时,初始化JS-Native Bridge,包含:组件的加载、模块的加载、已经main.js的加载;  那么本地js就有了js-native通讯的能力了。
    2. 请求指定的js URL文件:如:http://xxxx/helloWeex.js;
    3. js-Native 引擎运行解析 js文件。
    4. iOS RenderEngine 将js代码,通过转换成原生组件来渲染。

      这里就先简单的提下总体布局。下面的话题才是主题: iOS 是怎样实现 js 与 native交互的。 最后还是不忘weex本身的设计口号:Write once,run every wherer!

    二、iOS NativeBridge总设计原理

       2.0、要讲原理之前我们需要提出几个问题:

    • 如何初始化bridge 引擎?
    • 客户端是如何调用weex文件的?
    • 什么是组件,什么又是模块插件,为何要区分?
    • 如何实现自定义模块插件?
    • js和native通讯原理是什么,js和native是如何传参,又是如何实现回调功能呢?

      接下来我们一一回答上面问题:

      2.1、iOS 初始化weex 工程

      在我们工程已经集成weex的情况下,只要在应用启动时,初始以下代码即可:(当然前提是我们工程已经pod 'WeexSDK', '~> 0.11.0')

     1 - (void)initWeex {
     2     static dispatch_once_t onceToken;
     3     dispatch_once(&onceToken, ^{
     4         [WXAppConfiguration setAppGroup:@"xxxApp"];
     5         [WXAppConfiguration setAppName:@"WeexDemo"];
     6         [WXAppConfiguration setAppVersion:@"1.0.0"];
     7         [WXLog setLogLevel:1<<0];
     8         [WXSDKEngine initSDKEnvironment];
     9     });
    10 }

         对,iOS集成就是那么方便、简单、粗暴!

      2.2、客户端是如何调用weex文件的?

       其实从上面图1.0中可以很容易发现,其实客户端调用的是weex 转换为js后的js文件(这个文件其实可以是远程,当然也可以是本地的);

       利用WXSDKInstance类,进行对象管理,如下:

     1 @interface KBWeexShowcaseViewController ()
     2 @property (nonatomic, strong) WXSDKInstance *weexSDK;
     3 
     4 @end
     5 
     6 @implementation KBWeexShowcaseViewController
     7 
     8 - (void)viewDidLoad {
     9     [super viewDidLoad];
    10     // Do any additional setup after loading the view.
    11     self.view.backgroundColor = [UIColor whiteColor];
    12     self.title = @"我是第一个URL";
    13     
    14     self.weexSDK.viewController = self;
    15     self.weexSDK.frame = self.view.frame;
    16     
    17     [self.weexSDK renderWithURL:self.weexUri];
    18     
    19     __weak typeof(self) weakSelf = self;
    20     self.weexSDK.onCreate = ^(UIView *view) {
    21         [weakSelf.view addSubview:view];
    22     };
    23     
    24     self.weexSDK.renderFinish = ^(UIView *view) {
    25         view.backgroundColor = [UIColor yellowColor];
    26         NSLog(@"view:%@",view);
    27     };
    28     
    29     self.weexSDK.onFailed = ^(NSError *error) {
    30         NSLog(@"weexSDK onFailed : %@
    ", error);
    31     };
    32     
    33 }
    34 ......

      2.3、什么是组件,什么又是模块插件,为何要区分?

      作为iOS开发,估计对组件是很熟悉的吧:如UIButton、UILabel、UITableView等;所以理解weex的组件是同一个意思:组件主要是用来渲染UI层用的;

      而模块一般指具有独立功能的代码块,如:动画、存储、导航、分享,图片下载等;

      它之所以这么设计其实是为了解决实现 iOS 原生渲染的问题:即js代码渲染转化为原生组件来布局;

       当然在这里我提出一些疑问 :是全部原生化了吗?若全是原生化的话,那么事件是如何处理的?需要在运行时为类添加事件吗?又是如何添加的?等等。

      很多问题还要我现在无法回答,接下来几天当中我会慢慢去看下 iOS RenderEngine;

      2.4、如何实现自定义模块插件?

      实现自定义模块其实很简单:

      2.4.1、任意类实现WXModuleProtocol 接口即刻,如下:

    1 #import <WeexSDK/WeexSDK.h>
    2 @interface WXEventModule : NSObject<WXModuleProtocol>
    3 
    4 @end

      2.4.2、暴露需要开放给JS的接口,通过WX_EXPORT_METHOD 宏暴露给js ,如下:

     1 WX_EXPORT_METHOD(@selector(openURL:callback:))
     2 WX_EXPORT_METHOD(@selector(getString))
     3 
     4 
     5 - (void)openURL:(NSString *)url callback:(WXModuleCallback)callback
     6 {
     7     NSString *newURL = url;
     8     if ([url hasPrefix:@"//"]) {
     9         newURL = [NSString stringWithFormat:@"http:%@", url];
    10     } else if (![url hasPrefix:@"http"]) {
    11         newURL = [NSURL URLWithString:url relativeToURL:weexInstance.scriptURL].absoluteString;
    12     }
    13     UIViewController *controller = [[ViewController alloc] init];
    14     ((ViewController *)controller).url = [NSURL URLWithString:newURL];
    15     [[weexInstance.viewController navigationController] pushViewController:controller animated:YES];
    16     callback(@{@"result":@"success"});
    17 }
    18 
    19 
    20 - (NSString *)getString
    21 {
    22     return @"Kingbo Test String";
    23 }

        宏WX_EXPORT_METHOD:其实定义了一个函数,如上:其实定义了类似-(void) openURL##148 的函数,其返回值为"openURL:callback:";  

      其中第一个冒号前的名字作为js调用的方法名,原因很简单:安卓和js函数没有冒号;

      2.4.3、注册模块

      我们一般会将它和weex 初始化放在一起,如下:

      

     1 -(void)initWeex {
     2     --- xxxx ----
     6     [WXSDKEngine initSDKEnvironment];
     7     [WXLog setLogLevel:ULONG_MAX];
     8     
     9     //注册自己模块
    10     [self registMyModule];
    11 }
    12 
    13 -(void)registMyModule {
    14     [WXSDKEngine registerModule:@"event" withClass:NSClassFromString(@"WXEventModule")];
    15 
    16 }

      好了,到这里自定义就那么完成了,至于js怎么调用,嘻嘻,以后再说。。。。

      2.5、 js 和 native通讯原理

      其实最后一个问题就是以上的综合链接问题:如何将初始化、js实例化以及本地组件建立连接;

      下面UML 类关系图我自己整理了好久:(原图

      

     

                                                                    图2.1 Weex UML类图 

      从图2.1 不难发现 js 与 native 交互最终本质还是逃不过:JSValue 、JSContext 以及NSInvocation 类的调用;上图调用步骤已经大体还算清楚,暂时先不写了,以后有时间慢慢补全。

  • 相关阅读:
    self 和 super 关键字
    NSString类
    函数和对象方法的区别
    求两个数是否互质及最大公约数
    TJU Problem 1644 Reverse Text
    TJU Problem 2520 Quicksum
    TJU Problem 2101 Bullseye
    TJU Problem 2548 Celebrity jeopardy
    poj 2586 Y2K Accounting Bug
    poj 2109 Power of Cryptography
  • 原文地址:https://www.cnblogs.com/kingbo/p/6858065.html
Copyright © 2011-2022 走看看