iOS 熱加載之 JSPatch

zihuang12 8年前發布 | 11K 次閱讀 iOS開發 移動開發

來自: https://testerhome.com/topics/4084


起因

最近接了一些任務,為了將來應用更快的熱更新做準備,所以就查了一些文檔。查到了這個工具,在一陣惡心之后,大概略知一二了。其實感覺和之前這篇差不多,但又差別很大。沒有看過的同學可以先看lua in iOS

JSPatch

JSPatch是熱加載的方案,應該都是base在iOS上面的。我們可以在我們的pod文件中增加

platform :ios, '6.0'
pod 'JSPatch'

以引入這個模塊。

JSPatch在今天了解一下之后可以說是在OC和JS之間做了一個橋梁,并且適應性很好,在語法對應上也做的很好。但一般這種熱加載的框架并不是那么萬能。從JSPatch的定位和我自己用下來的感受來看,這個框架的確是為了修復一些bug而存在的,并不是真正的為了熱加載或者說專門為了應用熱加載存在的,至少我試下來目前局限性還是蠻大的。比如純粹的UIView適應性還很強,但其他各個控件的所有方法就不是全部兼容了,大家往下看吧。

AppDelegate.h

我們先來看官方文檔上面的demo吧。首先先來看AppDelegate.m

#import "AppDelegate.h"
#import "JPEngine.h"
#import "JPViewController.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    [JPEngine startEngine];
    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"monkey" ofType:@"js"];
    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
    [JPEngine evaluateScript:script];

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    JPViewController *rootViewController = [[JPViewController alloc] init];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
    self.window.rootViewController = navigationController;
    [self.window makeKeyAndVisible];

    return YES;
}
@end

這里和我們一般的iOS應用一樣,但有區別的是在復寫didFinishLaunchingWithOptions方法之后就啟動了JPEngine,也就是我們的JSPatch,接下來就是定義我們的文件名,我們的文件后綴,以及一系列界面的初始化。

JPViewController.h

接續來看這個界面的具體實現:

#import "JPViewController.h"

@implementation JPViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 50)];
    [btn setTitle:@"Push JPTableViewController" forState:UIControlStateNormal];
    [btn addTarget:self action:@user4(handleBtn:) forControlEvents:UIControlEventTouchUpInside];
    [btn setBackgroundColor:[UIColor grayColor]];
    [self.view addSubview:btn];


}

- (void)handleBtn:(id)sender
{
}

@end

這里不難理解。在界面上放了一個按鈕,定義了按鈕一系列的屬性。好了接下來就是關鍵了,一般在storyboard里面會直接去讓ide自動生成按鈕對應的sender方法,這里是定義了一個空方法。其實就很容易想到這個方法的實現必然就在JS里面了。

JS初始化類和方法

接著我們來看比較重要的js了。

defineClass('JPViewController', {
  handleBtn: function(sender) {
    var tableViewCtrl = JPTableViewController.alloc().init()
    self.navigationController().pushViewController_animated(tableViewCtrl, YES)
  }
})

首先JSPatch允許我們直接在js里面去定義新方法或者重新定義OC下面定義的類。比如這里我們重新定義了之后,在里面實現了我們的點擊方法并實現了一個TableView

defineClass('JPTableViewController : UITableViewController <UIAlertViewDelegate>', {
  dataSource: function() {
    var data = self.getProp('data')
    if (data) return data;
    var data = [];
    for (var i = 0; i < 20; i ++) {
      data.push("monkey test " + i);
    }
    self.setProp_forKey(data, 'data')
    return data;
  },

這里就開始進一步實現了,首先是table里面的數據。

JS重載OC方法

JSPatch里面會有一套很好的方法對應關系,同樣的方法,OC中如果是空格,JS就是,OC中如果是,那么JS中就是__。基本上就是這樣一個對應關系。我們來看下。

  • OC
//返回有多少個Sections 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView   
{  
    return 1;  
}  
  • JS
  numberOfSectionsInTableView: function(tableView) {
    return 1 ;
  },
  • OC
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section;
  • JS
 tableView_numberOfRowsInSection: function(tableView, section) {
    return self.dataSource().count();
  },
  • OC
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
  • JS
  tableView_cellForRowAtIndexPath: function(tableView, indexPath) {
    var cell = tableView.dequeueReusableCellWithIdentifier("cell") 
    if (!cell) {
            cell = require('UITableViewCell').alloc().initWithStyle_reuseIdentifier(0, "cell")


    }
    cell.textLabel().setText(self.dataSource().objectAtIndex(indexPath.row()))

    return cell
  },

如果想要調用OC原生組件的方法,可以先在JS最頭定義require就可以了。

DEMO效果

點擊按鈕進去之后的就是JS實現的界面和交互了。

其實也可以直接重載ViewDidLoad,這樣的話就可以直接去實現開始的界面。我們可以看下另外一個實現的界面,就會好很多。

require('UIColor,UIView,UILabel,UIFont,UIImageView,UIImage');

 本文由用戶 zihuang12 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!