IOS中Hybird的資料驅動與指令碼驅動的實現,ioshybird
現在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