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 类的调用;上图调用步骤已经大体还算清楚,暂时先不写了,以后有时间慢慢补全。

  • 相关阅读:
    LeetCode OJ Remove Duplicates from Sorted Array II
    LeetCode OJ 75. Sort Colors
    LeetCode OJ 74. Search a 2D Matrix
    LeetCode OJ 73. Set Matrix Zeroes
    Taglist
    NERDTree
    Beyond Compare 4
    Beyond compare vs kdiff3
    切換 java compiler 版本
    PE+ 1.0 ( Pump Express Plus 1.0 )
  • 原文地址:https://www.cnblogs.com/kingbo/p/6858065.html
Copyright © 2011-2022 走看看