ホームページ  >  記事  >  ウェブフロントエンド  >  JSとOC間の相互変調例を詳しく解説

JSとOC間の相互変調例を詳しく解説

零下一度
零下一度オリジナル
2017-05-10 11:06:101538ブラウズ

1. JavaScriptよく使用されるクラス

JavaScriptCore関数: JavaScriptCoreは、JSとOCの間の対話に使用されるAppleのネイティブAPIです。

JSContext: JS 実行環境。JS コードを実行し、それを通じて JS のデータを取得するために使用します。

JSValue: JS で取得されたデータ型を受け取るために使用されます。これは、任意のオブジェクトまたはメソッドにすることができます。

2. 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メソッドの定義を取得し、

を呼び出してJSメソッドを呼び出すOCを実装する

#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);
}

3. JSがOCのブロックを呼び出す

本質: 初めはJSにOCブロックがないので、 OC ブロックを直接呼び出す方法は、OC ブロックを取得し、JS でメソッドを生成し、それを JS 経由で呼び出す必要があります。

手順:

1. JS ランタイム環境を作成します

2. JS で対応する OC コードを生成します

3. JS を使用して、JS 環境で生成されたブロック メソッドを OC ブロックに呼び出すことができます。

3.1 JSがOCでパラメータなしのブロックを呼び出す

JS経由でOCでパラメータなしのブロックを呼び出したい

#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でパラメータなしのブロックを呼び出す

パラメータ付きのブロックを呼び出したいJS ブロックを介した OC

- (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];
}

4. JS が OC 内のクラスを呼び出す

本質: 最初に JS 内に OC クラスは存在せず、まず JS 内で OC クラスを生成し、それから JS を通してそれらを呼び出す必要があります。

手順

1. OC クラスは、JSExport プロトコルに準拠している必要があります

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 を継承し、どの属性を公開する必要があるかを記述するカスタム プロトコルを作成する必要もあります (システム クラスのどの属性を公開したいかは、独自のプロトコルで宣言するだけです)

ランタイム プロトコルを通じてクラスに追加します

カスタム プロトコル (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 - JavaScript ビデオ チュートリアル

以上がJSとOC間の相互変調例を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。