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代碼交互】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!