Files
knowledge-kit/Chapter1 - iOS/1.29.md
2020-02-25 17:46:51 +08:00

156 lines
5.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# JavascriptCore
1、JSCore 是基于 webkit 以 C/C++ 实现的一个 js 包装,让 js 和 Native 交互变得更加简单。
- JScontext
JSContext 代表一个 JavaScript 的执行环境的一个实例。所有JavaScript执行都是在上下文内进行。JSContext还用于管理对象的生命周期内 JavaScript 的虚拟机
- JSValue
JSValue 是用来接收 JSContext 执行后的返回结果。JSValue 可以是 JS 的任意类型(变量、对象、函数...
- JSManagedValue
JSManagedValue 是对 JSValue 的封装,可以解决 JS 和 OC 之间循环引用的问题。JSManagedValue 最常用的用法就是安全的从内存堆区里面引用 JSValue 对象.如果 JSValue 存储在内存的堆区的方式是不正确的,很容易造成循环引用,然后导致 JSContext 对象不能正确的释放掉.
- JSExport
是一个协议,用来将 Native 对象暴露给 JS这个对象可以指向给自身和别的对象。
- JSVirtualMachine
管理 JS 对象空间和所需的资源
2、Native 调用 JS
- 加载 JS 代码
(JSValue *)evaluateScript:(NSString *)script;
- 调用 JS 方法
JSvalue *callBack = self.context[@"sayHi"];
[callback callWithArguments:@[@"杭城小刘"]];
3、JS 调用 Native
- 通过 Block 实现。然后在 JS 中直接调用方法即可。需要注意的是在 Block 内部不要直接使用外部定义的 JScontext 对象或 JSValue ,应该作为参数传递进来,或者通过 + (JSContext *)currentContext; 来获取。否则会造成循环引用、内存无法被正确回收
self.context[@"showMessage"] = ^(NSString *message){
UIAlertController *alertCtr = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
[alertCtr addAction:cancel];
//注意方法是在子线程中执行的需要跟新UI的话需要切入主线程。
dispatch_async(dispatch_get_main_queue(), ^{
[weakSealf presentViewController:alertCtr animated:YES completion:nil];
});
};
- 通过 JSExport 协议实现; JS 需要通过 OC 中注入的对象来调方法,那么方法需要在协议中声明,并且在注入的对象中实现;在 webview 加载完成的时候注入实现协议的 Native 对象
//声明协议
@proptocol JSInject<JSExport>
- (void)showMessage:(NSString *)message;
@end
//实现相应的协议
- (void)showMessage:(NSString *)message{
UIAlertController *alertCtr = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
[alertCtr addAction:cancel];
//注意方法是在子线程中执行的需要跟新UI的话需要切入主线程。
dispatch_async(dispatch_get_main_queue(), ^{
[weakSealf presentViewController:alertCtr animated:YES completion:nil];
});
}
//注入
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//从webview上获取相应的JSContext。
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//注入JS需要的“OC”对象
self.context[@"Bridge"] = [JSInject new];
}
举个🌰
JS call Native
//对外要暴露的 native 对象(其中挂载了一些属性和方法)
#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>
@protocol PersonInjectExport<JSExport>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *hobby;
- (id)sayHi;
@end
@interface PersonInject : NSObject<PersonInjectExport>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *hobby;
- (id)sayHi;
@end
// viewcontroller
- (void)webViewDidFinishLoad:(UIWebView *)webView{
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
PersonInject *person = [[PersonInject alloc] init];
person.name = @"杭城小刘";
person.hobby = @"Coding、Movie、Music、Table tennis、Fit";
self.jsContext[@"lbp"] = person;
}
//JS
<body>
嗨。大家好我是
<p id="name">***</p>
<button id="show">那你做个自我介绍吧</button>
</body>
<script>
var u = navigator.userAgent
var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1
var isiOS = u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) //ios终端
document.getElementById("show").onclick = function () {
if (isiOS) {
document.getElementById("name").innerHTML = lbp.name;
setTimeout(() => {
alert(lbp.sayHi());
}, 1000);
}
}
</script>
Native call JS
//Native
- (void)callJS{
JSValue *functionName = self.jsContext[@"sum"];
NSInteger sum = [[functionName callWithArguments:@[@"2",@"18"]] toInt32];;
UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"来自JS 的计算" message:[NSString stringWithFormat:@"%zd",sum] preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
[alertVC addAction:okAction];
[self presentViewController:alertVC animated:YES completion:nil];
}
//JS
function sum(a ,b){
return parseInt(a) + parseInt(b);
}