IOS中Hybird实现

现在Hybird这块,网上也有很多文章,最近研究了下,分享给大家。

什么是Hybird技术?

1、一般是指WebView和Native技术混合而成的一套技术方案

2、也可以理解成,非Native技术与Native技术的混合开发

现在的Hybird有几种实现方式:

1、UIWebView、WKWebView 直接使用的是网页与OC交互(cordova与phonegap是使用该方案)(本文没有对该方案进行讲解)

2、数据驱动、脚本驱动(RN、微信小程序用的好像都是这种原理)

现在对于使用了webView实现的hybird技术大家都知道它的优势与劣势

优势是 可以热更新,直接WEB前端人员也能开发,擅长复杂的内容排版

劣势是 体验没有原生应用流畅

本文重点是说 数据驱动、脚本驱动,好处是能热更新,体验也更好,因为它都是生成原生应用,和WebView完全不一样

什么是数据驱动?

数据驱动说的是 我们App通过下载服务器端的json文件(里面定义了我们的UI布局样式,简单的业务功能)然后本地解析动态创建相应的UI。

什么是脚本驱动?

脚本驱动说的是 通过OC中的JavaScriptCore实现JS与OC的交互,一些简单的功能能放到JS中处理。

效果演示

默认打开效果:

点击测试1按钮的效果:

点击测试2按钮的效果:

以上的这些UI布局及功能都是动态写在 json与js 文件里面的 

具体代码演示

因为我们为了方便演示,我这里没有搭建WEB服务器,所以json文件就直接放在APP里面,我们先创建 page.json 和 page.js 文件 

分别如下:

可以看得出来,我们这个json文件里面的数据定义了一些UI的相关属性,注意button里面的那个onClicked,对应的是下面page.js里面的js方法

这里面的 updateLabelText 方法是我们App里面定义好的,下面我们来看App里

//
//  ViewController.m
//  hybirdDemo
//
//  Created by xgao on 17/3/3.
//  Copyright © 2017年 xgao. All rights reserved.
//

#import "ViewController.h"
//@import JavaScriptCore;
#import <JavaScriptCore/JavaScriptCore.h>

// 数据驱动、脚本驱动
@interface ViewController ()

// 用于执行JS的上下文
@property (nonatomic,strong) JSContext* jsContext;
// 保存按钮的点击事件的方法名
@property (nonatomic,retain) NSMutableDictionary* functionDic;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self initDataUI];
    [self initJSContext];
}

- (NSMutableDictionary*)functionDic{
    if (!_functionDic) {
        _functionDic = [NSMutableDictionary dictionary];
    }
    return _functionDic;
}

- (void)initDataUI{
    
    // 加载JSON数据
    NSString* pageJsonPath = [[NSBundle mainBundle] pathForResource:@"page" ofType:@"json"];
    NSData* pageJsonData = [NSData dataWithContentsOfFile:pageJsonPath];
    NSDictionary* pageJsonDic = [NSJSONSerialization JSONObjectWithData:pageJsonData options:NSJSONReadingAllowFragments error:nil];
    
    NSArray<NSDictionary*>* views = pageJsonDic[@"views"];
    for (NSDictionary* view in views) {
        // 解析UI
        if ([view[@"class"] isEqualToString:@"label"]) {    // UILabel
           
            UILabel* label = [[UILabel alloc]initWithFrame:[self CGRectWithDic:view]];
            label.text = view[@"text"];
            label.tag = [view[@"tag"] intValue];
            [self.view addSubview:label];
        }else if([view[@"class"] isEqualToString:@"button"]){   // UIButton
            
            UIButton* button = [[UIButton alloc]initWithFrame:[self CGRectWithDic:view]];
            [button setTitle:view[@"title"] forState:UIControlStateNormal];
            button.tag = [view[@"tag"] intValue];
            [button setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
            [button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
            // 添加到事件字典中,btnClick
            [self.functionDic setObject:button forKey:view[@"onClicked"]];
            [self.view addSubview:button];
        }
    }
}

// 初始化JSContext
- (void)initJSContext{
    
    self.jsContext = [[JSContext alloc]init];
    
    // 加载 page.js 脚本文件
    NSString* pageJsPath = [[NSBundle mainBundle] pathForResource:@"page" ofType:@"js"];
    NSString* pageJs = [NSString stringWithContentsOfFile:pageJsPath encoding:NSUTF8StringEncoding error:nil];
    // 执行JS脚本,将JS代码注入到 上下文中
    [self.jsContext evaluateScript:pageJs];
    
    // 定义updateLabelText方法,用于JS调用OC
    __weak ViewController* weakSelf = self;
    self.jsContext[@"updateLabelText"] = ^(NSString* text,NSInteger tag){
        UILabel* label = [weakSelf.view viewWithTag:tag];
        label.text = text;
    };
}

// button按钮点击通用事件
- (void)buttonClick:(UIButton*)button{
    
    for (NSString* func in self.functionDic.allKeys) {
        UIButton* btn = self.functionDic[func];
        if ([btn isEqual:button]) {
            // OC 调用 JS 方法,这里就是 OC调用JS定义的那两个 btnClick 和 btnClick2
            [self.jsContext[func] callWithArguments:nil];
            break;
        }
    }
    
}

#pragma mark - Private

- (CGRect)CGRectWithDic:(NSDictionary*)dic{
    
    CGFloat x = [dic[@"x"] floatValue];
    CGFloat y = [dic[@"y"] floatValue];
    CGFloat width = [dic[@"width"] floatValue];
    CGFloat height = [dic[@"height"] floatValue];
    return CGRectMake(x, y, width, height);
}

@end
原文地址:https://www.cnblogs.com/xgao/p/6497012.html