mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-25 04:17:17 +00:00
Add Chapter1 iOS notes on various topics
This commit is contained in:
155
Chapter1 - iOS/1.29.md
Normal file
155
Chapter1 - iOS/1.29.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# JavascriptCore
|
||||
|
||||
1. JSCore is a JavaScript wrapper implemented in C/C++ based on WebKit that makes interaction between JavaScript and native code simpler.
|
||||
|
||||
- JSContext
|
||||
JSContext represents an instance of a JavaScript execution environment. All JavaScript execution occurs inside a context. JSContext is also used to manage the lifecycle of JavaScript objects in the VM.
|
||||
|
||||
- JSValue
|
||||
JSValue is used to receive the return results from JSContext execution. A JSValue can be any JavaScript type (primitive, object, function, etc.).
|
||||
|
||||
- JSManagedValue
|
||||
JSManagedValue is a wrapper around JSValue that helps resolve retain-cycle issues between JS and Objective-C. The most common use is to safely reference a JSValue stored on the heap. If a JSValue is stored on the heap incorrectly, it can easily create retain cycles that prevent JSContext from being released properly.
|
||||
|
||||
- JSExport
|
||||
A protocol used to expose native objects to JS; the exposed object can point to itself and to other objects.
|
||||
|
||||
- JSVirtualMachine
|
||||
Manages the JS object space and needed resources.
|
||||
|
||||
2. Native calling JS
|
||||
|
||||
- Load JS code
|
||||
(JSValue *)evaluateScript:(NSString *)script;
|
||||
|
||||
- Call JS function
|
||||
JSValue *callback = self.context[@"sayHi"];
|
||||
[callback callWithArguments:@[@"Hangzhou Xiao Liu"]];
|
||||
|
||||
3. JS calling Native
|
||||
|
||||
- Implement via a block. Then call the method directly from JS. Note: inside the block do not directly use externally defined JSContext or JSValue; pass them as parameters or obtain them via + (JSContext *)currentContext; otherwise it may cause retain cycles and memory won't be freed correctly.
|
||||
self.context[@"showMessage"] = ^(NSString *message){
|
||||
UIAlertController *alertCtr = [UIAlertController alertControllerWithTitle:@"Notice" message:message preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
|
||||
[alertCtr addAction:cancel];
|
||||
// Note: the block executes on a background thread; update UI on main thread.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[weakSelf presentViewController:alertCtr animated:YES completion:nil];
|
||||
});
|
||||
};
|
||||
|
||||
- Implement via the JSExport protocol; JS will call methods on an injected Objective-C object, so the methods must be declared in the protocol and implemented on the injected object. Inject the native object when the web view finishes loading.
|
||||
// Protocol declaration
|
||||
|
||||
@protocol JSInject <JSExport>
|
||||
- (void)showMessage:(NSString *)message;
|
||||
@end
|
||||
|
||||
// Implementation
|
||||
|
||||
- (void)showMessage:(NSString *)message{
|
||||
UIAlertController *alertCtr = [UIAlertController alertControllerWithTitle:@"Notice" message:message preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
|
||||
[alertCtr addAction:cancel];
|
||||
// Note: the method runs on a background thread; update UI on main thread.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[weakSelf presentViewController:alertCtr animated:YES completion:nil];
|
||||
});
|
||||
}
|
||||
|
||||
// Injection
|
||||
|
||||
- (void)webViewDidFinishLoad:(UIWebView *)webView
|
||||
{
|
||||
// Get the JSContext from the web view.
|
||||
self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
|
||||
|
||||
// Inject the Objective-C object needed by JS
|
||||
self.context[@"Bridge"] = [JSInject new];
|
||||
}
|
||||
|
||||
|
||||
Example
|
||||
|
||||
JS calls Native
|
||||
|
||||
// Native object to expose (with some properties and methods)
|
||||
#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
|
||||
|
||||
|
||||
// view controller
|
||||
|
||||
- (void)webViewDidFinishLoad:(UIWebView *)webView{
|
||||
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
|
||||
PersonInject *person = [[PersonInject alloc] init];
|
||||
person.name = @"Hangzhou Xiao Liu";
|
||||
person.hobby = @"Coding, Movie, Music, Table tennis, Fit";
|
||||
self.jsContext[@"lbp"] = person;
|
||||
}
|
||||
|
||||
// JS
|
||||
<body>
|
||||
|
||||
Hi. Hello everyone, I am
|
||||
<p id="name">***</p>
|
||||
|
||||
<button id="show">Then do an introduction</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 device
|
||||
|
||||
document.getElementById("show").onclick = function () {
|
||||
if (isiOS) {
|
||||
document.getElementById("name").innerHTML = lbp.name;
|
||||
setTimeout(() => {
|
||||
alert(lbp.sayHi());
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
Native calls JS
|
||||
|
||||
// Native
|
||||
- (void)callJS{
|
||||
JSValue *functionName = self.jsContext[@"sum"];
|
||||
NSInteger sum = [[functionName callWithArguments:@[@"2",@"18"]] toInt32];
|
||||
|
||||
UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"Calculation from 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);
|
||||
}
|
||||
Reference in New Issue
Block a user