你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS中應用JSPatch框架使Objective-C與JavaScript代碼交互

iOS中應用JSPatch框架使Objective-C與JavaScript代碼交互

編輯:IOS開發綜合

JSPatch是GitHub上一個開源的框架,其可以經由過程Objective-C的run-time機制靜態的應用JavaScript挪用與調換項目中的Objective-C屬性與辦法。其框架玲珑,代碼簡練,而且經由過程體系的JavaScriptCore框架與Objective-C停止交互,這使其在平安性和審核風險上都有很強的優勢。Git源碼地址:https://github.com/bang590/JSPatch。

1、從一個官方的小demo看起

經由過程cocoapods將JSPath集成進一個Xcode工程中,在AppDelegate類的中編寫以下代碼:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  //開端初始化引擎
  [JPEngine startEngine];
  //讀取js文件
  NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];
  NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
  //運轉js文件
  [JPEngine evaLuateScript:script];
  self.Window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
  self.Window.rootViewController = [[ViewController alloc]init];
  [self.window addSubview:[self genView]];
  [self.window makeKeyAndVisible];
  return YES;
}

- (UIView *)genView
{
  UIView * view= [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
  view.backgroundColor = [UIColor redColor];
  return view;
}

在工程中添加一個js文件,編寫以下:

  

 require('UIView, UIColor, UILabel')
  //要調換函數的類
  defineClass('AppDelegate', {
      //調換函數
        //要調換函數的稱號
        genView: function() {
          var view = self.ORIGgenView();
          view.setBackgroundColor(UIColor.greenColor())
          var label = UILabel.alloc().initWithFrame(view.frame());
          label.setText("JSPatch");
          label.setTextAlignment(1);
          view.addSubview(label);
          return view;
      }
  });

運轉工程,可以看到genView辦法被調換成了js文件中的辦法,本來白色的視圖被修正成了綠色。

2、應用JavaScript代碼向Objective-C中修正或添加辦法

JSPatch引擎中支撐3中方法停止JavaScript代碼的挪用,分離是應用JavaScript字符串停止代碼運轉,讀取當地的JavaScript文件停止代碼運轉和獲得收集的JavaScript文件停止代碼運轉。例如,假如想要經由過程JavaScript代碼在項目中彈出一個正告框,在Objective-C代碼中拔出以下代碼:

- (void)viewDidLoad {
  [super viewDidLoad];
  // ‘\'符用於停止換行
  [JPEngine evaLuateScript:@"\
   var alertView = require('UIAlertView').alloc().init();\
   alertView.setTitle('Alert');\
   alertView.setMessage('AlertView from js'); \
   alertView.addButtonWithTitle('OK');\
   alertView.show(); \
   "];
}

開辟者也能夠靜態在Objective-C類文件中添加辦法,例如在ViewController類中編寫以下:

- (void)viewDidLoad {
  [super viewDidLoad];
  self.view.backgroundColor = [UIColor whiteColor];
  [JPEngine startEngine];
  NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];
  NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
  [JPEngine evaLuateScript:script];
  [self performSelectorOnMainThread:@selector(creatView) withObject:nil waitUntilDone:nil];
}

JavaScript文件代碼以下:

 require('UIView, UIColor, UILabel')
  defineClass('ViewController', {
      // replace the -genView method
        creatView: function() {
          var view = UIView.alloc().initWithFrame({x:20, y:20, width:100, height:100});
          view.setBackgroundColor(UIColor.greenColor());
          var label = UILabel.alloc().initWithFrame({x:0, y:0, width:100, height:100});
          label.setText("JSPatch");
          label.setTextAlignment(1);
          view.addSubview(label);
        self.view().addSubview(view)
      }
  });

除下面的代碼,在ViewController.m文件中沒有編寫任何其他的辦法,運轉工程,可以看到法式並沒有瓦解,ViewController履行了creatView辦法。

經由過程下面的示例,我們發明應用JSPatch可以做一些非常風趣的事。關於IOS運用來講,經由過程官方渠道AppStore停止運用法式的宣布要經由過程人工審核,有時這個審核周期會異常長,假如在開辟者在編寫代碼時留下了一些小破綻,運用一旦上線,若要修正失落這個bug就非常艱苦了。有了JSPatch,我們可以想象,假如可以定位到線上運用有成績的辦法,應用JS文件來修正失落這個辦法,這將是何等cool的一件事,現實上,JSPatch的重要用處也是可以完成線上運用極小成績的hotfix。

3、JavaScript與Objective-C交互的基本辦法

要應用JSPatch來停止Objective-C作風的辦法編寫,須要遵照一些JavaScript與Objective-C交互的規矩。

1.在JavaScript文件中應用Objective-C類

在編寫JavaScript代碼時假如須要用到Objective-C的類,必需先對這個類停止require援用,例如,假如須要應用UIView這個類,須要在應用進步行以下援用:

require('UIView')

異樣也能夠一次對多個Objective-C類停止援用:

require('UIView, UIColor, UILabel')

還有一種加倍輕便的寫法,直接在應用的時刻對其停止援用:

require('UIView').alloc().init()

2.在JavaScript文件中停止Objective-C辦法的挪用

在停止Objective-C辦法的挪用時,分為兩種,一種是挪用類辦法,一種是挪用類的對象辦法。

挪用類辦法:經由過程類名打點的方法來挪用類辦法,格局相似以下,括號內為參數傳遞:

UIColor.redColor()

挪用實例辦法:經由過程對象打點的方法挪用類的實例辦法,格局以下,括號內為參數傳遞:

view.addSubview(label)

關於Objective-C中的多參數辦法,轉化為JavaScript將參數朋分的地位以_停止朋分,參數全體放入前面的括號中,以逗號朋分,示例以下:

view.setBackgroundColor(UIColor.colorWithRed_green_blue_alpha(0,0.5,0.5,1))
關於Objective-C類的屬性變量,在JavaScript中只能應用getter與setter辦法來拜訪,示例以下:

label.setText("JSPatch")

提醒:假如原Objective-C的辦法中曾經包括了_符號,則在JavaScript中應用__取代。

3.在JavaScript中操作與修正Objective-C類

JSPatch的最年夜運用是在運用運轉時靜態的操作和修正類。

重寫或許添加類的辦法:

在JavaScript中應用defineClass來界說和修正類中的辦法,其編寫格局以下所示:

/*
classDeclaration:要添加或許重寫辦法的類名 字符串 假如此類不存在 則會創立新的類
instanceMethods:要添加或許重寫的實例辦法 {}
classMethods:要添加或許重寫的類辦法 {}
*/
defineClass(classDeclaration, instanceMethods, classMethods)

示例以下:

defineClass('ViewController', {
      // replace the -genView method
        newFunc: function() {
          //編寫實例辦法
          self.view().setBackgroundColor(UIColor.redColor())
        }
  
      },{

        myLoad:function(){
          //編寫類辦法
        }

      }
      )

假如在重寫了類中的辦法後要挪用原辦法,須要應用ORIG前綴,示例以下:

defineClass('ViewController', {
      // replace the -genView method
        viewDidLoad: function() {
          //編寫實例辦法
          self.ORIGviewDidLoad()
        }
  
      }
      )

關於Objective-C中super症結字挪用的辦法,在JavaScript中可使用self.super()來挪用,例如:

defineClass('ViewController', {
      // replace the -genView method
        viewDidLoad: function() {
          //編寫實例辦法
          self.super().viewDidLoad()
        }
  
      }
      )

異樣JSPatch也能夠為類添加暫時屬性,用於在辦法間參數傳遞,應用set_Prop_forKey()來添加屬性,應用getProp()來獲得屬性,留意,JSPatch添加的屬性不克不及應用Objective-C的setter與getter辦法拜訪,以下:

defineClass('ViewController', {
      // replace the -genView method
        viewDidLoad: function() {
          //編寫實例辦法
          self.super().viewDidLoad()
          self.setProp_forKey("JSPatch", "data")
        },
        touchesBegan_withEvent(id,touch){
          self.getProp("data")
          self.view().setBackgroundColor(UIColor.redColor())
        }
  
      }
      )

關於為類添加協定的遵照,和Objective-C中遵照協定的方法分歧,以下:

defineClass("ViewController2: UIViewController <UIAlertViewDelegate>", {
      viewDidAppear: function(animated) {
      var alertView = require('UIAlertView')
      .alloc()
      .initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles(
                                        "Alert",
                                        "content",
                                        self,
                                        "OK",
                                        null
                                        )
      alertView.show()
      },
      alertView_clickedButtonAtIndex:function(alertView, buttonIndex) {
      console.log('clicked index ' + buttonIndex)
      }
      })

4、JavaScript與Objective-C交互的幾種經常使用類型

1.構造體

在Objective-C代碼中,我們常常會應用到構造體,JSPatch華夏生支撐的構造體有以下幾種:CGPoint,CGSize,CGRect,NSRange。而且這幾種構造體在停止界面操作時也會常常應用到。

關於CGRect類型,JavaScript應用以下代碼創立:

  var view = require('UIView').alloc().init()
  view.setFrame({x:100,y:100,width:100,height:100})

關於CGPoint類型,JavaScript應用以下代碼創立:

   

view.setCenter({x:200,y:200})

關於CGSize類型,JavaScript應用以下代碼創立:

  var size = {width:200,height:200}
  view.setFrame({x:100,y:100,width:size.width,height:size.height})

關於NSRange類型,JavaScript應用以下代碼創立:

  var range = {location: 0, length: 1}

2.選擇器Selector

關於Objective-C中的辦法選擇器Selector,在JavaScript中應用字符串的情勢創立,例如:

self.performSelector_withObject("func:", 1)

3.關於空對象

在JavaScript中,null與undefined都對應於Objective-C中的nil,Objective-C中的NSNull空對象,在JavaScript中應用nsnull來取代。

4.在Objective-C與JavaScript中停止block的交互

在JavaScript與Objective-C停止block交互有兩種方法,一種是在JavaScript文件中挪用Objective-C中的block,一種是將JavaScript文件中的函數塊作為block參數傳遞給Objective-C。

在JavaScript文件中應用Objective-C中的block非常簡略,由於JavaScript中沒有block的概念,Objective-C會被主動轉換為函數,示例以下:

Objective-C:

typedef void(^block)(NSString * str);
@interface ViewController ()
@end
@implementation ViewController
-(block)getBlock{
  block block = ^(NSString * str){NSLog(@"%@",str);};
  return block;
}
@end

JavaScript:

defineClass("ViewController", {
      viewDidAppear: function(animated) {
       var func = self.getBlock()
        func("123")
      }
      })

在JavaScript文件中將func作為參數block傳遞給Objective-C就龐雜一些,須要應用block()辦法停止包裝,例如:

Objective-C:

@interface ViewController ()
@end
@implementation ViewController

-(void)run:(void(^)(NSString * str))block{
  block(@"123");
}
@end

JavaScript:

defineClass("ViewController", {
      viewDidAppear: function(animated) {
      //run 辦法中須要傳入一個block
      self.run(block("NSString*",function(str){console.log(str)}))
      }
      })

在應用block()辦法對JavaScript中的Func停止包裝時,block(param1,param2)有兩個參數,第1個參數設置func中的參數類型,假如有多個參數,應用逗號朋分;第2個參數為func函數體。

留意:在block()包裝的func中弗成以應用self指針,假如須要應用self,須要在block外停止暫時變量的轉換,示例以下:

defineClass("ViewController", {
      viewDidAppear: function(animated) {
      //run 辦法中須要傳入一個block
      var slf = self
      self.run(block("NSString*",
              function(str){
              console.log(str)
              slf.log(str)
              }))
      }
      })

在JavaScript平分別應用__weak()與__strong來聲明弱援用與強援用對象,例如:

 var slf = __weak(self)
 var stgSef = __strong(self)

5.關於GCD與列舉

在JSPatch中,可使用以下JavaScript代碼來挪用GCD辦法:

//壅塞以後線程必定時光
dispatch_after(1.0, function(){ 
})
//為主線程添加異步義務
dispatch_async_main(function(){ 
})
//為主線程添加同步義務
dispatch_sync_main(function(){ 
})
//向全局隊列中添加義務
dispatch_async_global_queue(function(){ 
})
JSPatch中弗成以直接應用Objective-C中界說的列舉,然則可以用其列舉的真實值停止傳遞。例如:

//UIControlEventTouchUpInside的值是1<<6
btn.addTarget_action_forControlEvents(self, "handleBtn", 1<<6);

【iOS中應用JSPatch框架使Objective-C與JavaScript代碼交互】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved