JavaScript Core for OC and JS Interaction

Keywords: Javascript iOS Mobile

Reprinted from: http://www.cnblogs.com/markstray/p/5757255.html

JavaScript Core provides the Obj-C API bridged by JavaScript and Objective-C. JavaScript Core provides the ability to execute JavaScript scripts without UIWebView, and seamlessly transfer values or objects between Objective-C and JavaScript using modern Objective-C grammars such as Blocks and subscripts. With JavaScript Core, we can communicate between OC and JS with very little code. Let's see how it works. Similarly, this article will rewrite the previous article with JavaScript Core API

Overview of JavaScript Core

To use JavaScript Core, you need to import the header file " import __________

#import "JSContext.h"
#import "JSValue.h"
#import "JSManagedValue.h"
#import "JSVirtualMachine.h"
#import "JSExport.h"

JSContext: Represents the running environment of JavaScript. After creating JSContext, you can execute JavaScript code.

JSValue: Represents JavaScript entities. A JSValue can be any type of JavaScript: strings and numbers; arrays, objects and methods; and even errors and special JavaScript values such as null and undefined. Any JSContext value is wrapped in a JSValue object.

JSManagedValue: It is essentially a JSValue, which is used to deal with some special situations in memory management. It can help OC reference technology and JS garbage collection to make the correct conversion between the two memory management mechanisms.

JSExport: This is a protocol that can be used to export native objects to JavaScript, so that the attributes or methods of native objects become attributes or methods of JavaScript.

JSVirtual Machine: Represents an object space, has its own heap structure and garbage collection mechanism, is the basis of running JS code. In most cases, there is no need to interact directly with it unless some special multithreading or memory management issues are addressed.

Back to the top
2. JavaScript Core Deepening

  1. Method call

OC calls JS

//Execution of js scripts using UIWebView
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

//Method of executing js scripts with JSContext
- (JSValue *)evaluateScript:(NSString *)script;

//js script execution using JSValuet
- (JSValue *)callWithArguments:(NSArray *)arguments;

b. JS calls OC

There are two ways: block and JSExport protocol

block can directly talk about a function, inject it into JSContext, make it call, but pay attention to memory leak.

By inheriting the JSExport protocol, OC methods and attributes can be injected into JSContext and then invoked

  1. error handling

When an exception occurs at JavaScript runtime, the Block set in JSContext's exception handler is called back and error handling is performed on the OC side.

context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
      NSLog(@"JS Error: %@", exception);
};
  1. memory management

Object-C's memory management mechanism is reference counting, and JavaScript's memory management mechanism is garbage collection. In most cases, JavaScript Core can achieve seamless and error-free conversion between the two memory management mechanisms, but in a few cases, JSManagedValue objects are needed to solve the problem, and the corresponding links will be given later.

Back to the top
3. Rewriting with JavaScript Core

Following the previous example, no changes have been made elsewhere, only the relevant codes for bilateral interactions have been modified:

OC terminal:

  1. Initialize JScontext
self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
  1. Injecting JS code
__block typeof(self) weakSelf = self;
//JS calls OC method list
self.jsContext[@"showMobile"] = ^ {
    dispatch_async(dispatch_get_main_queue(), ^{
        [weakSelf showMsg:@"I'm Xiao Hong's cell phone number below.:18870707070"];
    });
};

self.jsContext[@"showName"] = ^ (NSString *name) {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSString *info = [NSString stringWithFormat:@"Hello %@, Nice to meet you",name];
        [weakSelf showMsg:info];
    });
};

void (^_showSendMsg) (NSString *num, NSString *msg) = ^ (NSString *num, NSString *msg) {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSString *info = [NSString stringWithFormat:@"This is my mobile number.: %@, %@ !!",num,msg];
        [self showMsg:info];
    });
};

[self.jsContext setObject:_showSendMsg forKeyedSubscript:@"showSendMsg"];
  1. Executing JS-side code
//OC calls JS method list
- (IBAction)btnClick:(UIButton *)sender {
    if (sender.tag == 123) {
        //Using jsContext
        [self.jsContext evaluateScript:@"alertMobile()"];
    }

    if (sender.tag == 234) {
        //Using webView
        [self.webView stringByEvaluatingJavaScriptFromString:@"alertName('Xiaohong')"];
    }

    if (sender.tag == 345) {
        //Using jsValue
        JSValue *jsValue = [self.jsContext objectForKeyedSubscript:@"alertSendMsg"];
        [jsValue callWithArguments:@[@"18870707070",@"It's really a pleasure to climb mountains on weekends."]];
    }
}

JS terminal:

//List of methods provided to OC to invoke JS
function alertMobile() {
    alert('I'm Xiao Huang's cell phone number above.:13300001111')
}

function alertName(msg) {
    alert('Hello ' + msg + ', Nice to meet you, too')
}

function alertSendMsg(num,msg) {
    alert('This is my mobile number.:' + num + ',' + msg + '!!')
}

//List of JS response methods
function btnClick1() {
    showMobile()
}

function btnClick2() {
    showName('xiaohuang')
}

function btnClick3() {
    showSendMsg('13300001111', 'Go Climbing This Weekend !!!')
}

Knowing the principles and core files of JavaScript Core, the role of core classes, and then rewriting them, there is no hindrance, but there is still something to be noticed. Because JavaScript is single-threaded, the code that calls OC in JS is executed in the thread, so we need to switch to the main thread to refresh the operation related to the interface. The other processes are consistent with the previous ones. Learning this part refers to a lot of other materials. The article later gives an introduction to JavaScript Core and a link to the article on the implementation of principle parsing. Interested students can In-depth learning through transmission

Four, postscript

Apple's technology is updated every year. In JavaScript, there will be new surprises every year. When iOS 8 was released, Apple launched WK WebView. It rebuilt the previous UIWebView completely (reconstructing UIWebView and UIWebView Delegate into 14 classes and 3 protocols). Its functions are more perfect and powerful, and its stability and performance are also improved significantly. I saw an article before, which introduced the relevant API of WKWebView in detail. It helped me to understand this module. I also read the whole API of WKWebView systematically. When I read it, I didn't read the article directly. I read the API myself first and then compared it to see the differences and differences in understanding. At the same time, I was deeply impressed. Students can also learn from this way. In the next article, we use the relevant APIs of WK WebView to complete this example

Stamp here: Welcome star to the DEMO address of this article

References (stamp here):

http://nshipster.cn/javascriptcore/

https://hjgitbook.gitbooks.io/ios/content/04-technical-research/04-javascriptcore-note.html

JavaScriptCore Principle Analysis Series of Realization

Posted by Kulak on Mon, 25 Mar 2019 01:45:29 -0700