首頁  >  文章  >  web前端  >  JS與OC互調的實例詳解

JS與OC互調的實例詳解

零下一度
零下一度原創
2017-05-10 11:06:101595瀏覽

一、JavaScriptCore常用的類別

JavaScriptCore作用:JavaScriptCore是蘋果原生API,用來JS和OC交互的。

JSContext: JS運行環境,用它去執行JS程式碼,並且透過它去取得JS裡的資料

JSValue: 用來接收JS中取得的資料類型,可以是任一對象,方法。

二、OC呼叫JS

本質:JS程式碼中已經定義好變數和方法,透過OC去獲取,並且呼叫

步驟:

1.建立JS運行環境

2.執行JS程式碼

3.取得JS數據(變量,方法)

4.使用JS數據,方法

2.1 取得定義在JS中的變數

可以直接透過OC修改JS中變數的值

#pragma mark - 获取JS中定义的变量
- (void)getJSVar{
// JS代码
NSString *jsCode = @"var arr = [1,2,3]";
// 创建JS运行环境
JSContext *ctx = [[JSContext alloc] init];
// 执行JS代码
[ctx evaluateScript:jsCode];
// 因为变量直接定义在JS中,所以可以直接通过JSContext获取,根据变量名称获取,相当于字典的Key
// 只有先执行JS代码,才能获取变量
JSValue *jsArr = ctx[@"arr"]; 
  jsArr[0] = @5;
// 打印结果:5,2,3
NSLog(@"%@",jsArr);}

2.2 取得定義在JS中的方法,並且調用

實作OC呼叫JS方法

#pragma mark - OC调用JS
// OC调用JS方法,并获取返回结果
- (void)ocCallJSFunc{
NSString *jsCode =@"function hello(say){"
" return say; "
"}";
// 创建JS运行环境
JSContext *ctx = [[JSContext alloc] init];
// 因为方法直接定义在JS中,所以可以直接通过JSContext获取,根据方法名称获取,相当于字典的Key
// 执行JS代码
[ctx evaluateScript:jsCode];
// 获取JS方法,只有先执行JS代码,才能获取
JSValue *hello = ctx[@"hello"];
// OC调用JS方法,获取方法返回值
JSValue *result = [hello callWithArguments:@[@"你好"]];
// 打印结果:你好
NSLog(@"%@",result);
}

三、JS呼叫OC中的block

本質:一開始JS中並沒有OC的block,所以沒辦法直接呼叫OC的block,需要把OC的block,在JS中產生方法,然後透過JS呼叫。

步驟:

1.建立JS運行環境

2.在JS中產生對應的OC代碼

3.使用JS調用,在JS環境中產生的block方法,就能呼叫到OC的block中.

3.1 JS呼叫OC中不帶參數的block

想透過JS呼叫OC中不帶參數的block

#pragma mark - JS调用OC中不带参数的block
- (void)jsCallOCBlock1WithNoneArguments{
// 创建JS运行环境
JSContext *ctx = [[JSContext alloc] init];
// JS调用Block方式// 由于JS本身没有OC这个代码,需要给JS中赋值,就会自动生成右边的代码.
// 相当于在JS中定义一个叫eat的方法,eat的实现就是block中的实现,只要调用eat,就会调用block
ctx[@"eat"] = ^(){NSLog(@"吃东西"); 
  };
// JS执行代码,就会直接调用到block中
NSString*jsCode =@"eat()"; 
  [ctx evaluateScript:jsCode];}

3.2 JS呼叫OC中帶參數的block

想透過JS呼叫OC中帶參數的block

- (void)jsCallOCBlockWithArguments{
// 创建JS运行环境
JSContext *ctx = [[JSContext alloc] init];
// 2.调用带有参数的block
// 还是一样的写法,会在JS中生成eat方法,只不过通过[JSContext currentArguments]获取JS执行方法时的参数
ctx[@"eat"] = ^(){
// 获取JS调用参数
NSArray *arguments = [JSContext currentArguments];
NSLog(@"吃%@",arguments[0]); 
  };
// JS执行代码,调用eat方法,并传入参数面包
NSString*jsCode =@"eat('面包')"; 
  [ctx evaluateScript:jsCode];
}

#四、JS調用OC中的類別

#本質:一開始JS中並沒有OC的類,需要先在JS中產生OC的類,然後在透過JS呼叫。

步驟

1.OC類別必須遵守JSExport協議,只要遵守JSExport協議,JS才會產生這個類別

2.但是還不夠,類別裡面有屬性和方法,也要在JS中產生

3.JSExport本身不自帶屬性和方法,需要自訂一個協議,繼承JSExport,在自己的協議中暴露需要在JS中用到的屬性和方法

4.這樣自己的類別只要繼承自己的協議就好,JS就會自動生成類,包括自己協議中聲明的屬性和方法

4.1 JS呼叫OC自訂類別

自訂協定(PersonJSExport)

@protocolPersonJSExport
@property(nonatomic, strong) NSString *name;
-(void)play;
// 调用多个参数的方法,JS函数命名规则和OC还不一样,很可能调用不到对应的JS生成的函数,为了保证生成的JS函数和OC方法名一致,OC提供了一个宏JSExportAs,用来告诉JS应该生成什么样的函数对应OC的方法,这样就不会调错了。
// PropertyName:JS函数生成的名字
// Selector:OC方法名
// JS就会自动生成playGame这个方法JSExportAs(playGame,
- (void)playWithGame:(NSString *)gametime:(NSString *)time);
@end

自訂類別(Person)

#
@interfacePerson: NSObject
@property(nonatomic, strong) NSString *name;
-(void)playWithGame:(NSString*)gametime:(NSString*)time;
@end
@implementationPerson
-(void)play{
NSLog(@"%@玩",_name);
}
-(void)playWithGame:(NSString*)gametime:(NSString*)time{
NSLog(@"%@在%@玩%@",_name,time,game);
}
@end

透過JS呼叫OC自訂類別

#pragmamark - JS调用OC自定义类
- (void)jsCallOCCustomClass{
// 创建Person对象
Person *p = [[Person alloc] init];   
p.name = @"zs";   
JSContext *ctx = [[JSContext alloc] init];
// 会在JS中生成Person对象,并且拥有所有值
// 前提:Person对象必须遵守JSExport协议,
ctx[@"person"] = p;
// 执行JS代码
// 注意:这里的person一定要跟上面声明的一样,因为生成的对象是用person引用// NSString *jsCode = @"person.play()";
NSString *jsCode = @"person.playGame('德州扑克','晚上')"; 
  [ctx evaluateScript:jsCode];
}

4.1 JS呼叫OC系統類別

問題:系統自帶的類,想要透過JS調用怎麼辦,我們又沒辦法修改系統自帶類別的檔案

和呼叫自訂類別一樣,也要弄個自訂協定繼承JSExport,描述需要暴露哪些屬性(想要把系統類別的哪些屬性暴露,就在自己的協定宣告)

透過runtime,給類別新增協定

自訂協定(UILabelJSExport)

@protocolUILabelJSExport
@property(nonatomic, strong) NSString *text;
@end

#JS調用OC系統類別

#pragma mark - JS调用OC系统类
- (void)jsCallOCSystemClass{ 
  // 给系统类添加协议 class_addProtocol([UILabel class],
@protocol(UILabelJSExport)); 
  // 创建UILabel 
UILabel *label= [[UILabel alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
[self.view addSubview:label];
JSContext *ctx = [[JSContext alloc] init];   
// 就会在JS中生成label对象,并且用laebl引用
ctx[@"label"] =label;
// 利用JS给label设置文本内容
NSString *jsCode = @"label.text = 'Oh Year'"; 
  [ctx evaluateScript:jsCode];
}

【相關推薦】

1. 免費js線上影片教學

2. # JavaScript中文參考手冊

3. php.cn獨孤九賤(3)-JavaScript影片教學

#

以上是JS與OC互調的實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn