JavaScript: Talking about the interactive-javascriptcore framework between iOS and H5
Objective
Small as an iOS program ape, may study JavaScript and H5 related knowledge is not to really want to switch to do this aspect, in fact, in order to study the JavaScriptCore framework in OC, The JavaScriptCore framework is primarily used to enable iOS to interact with H5. Of course, the earliest I ever wrote about iOS WebView a usage of JS. (Get rid of the ads on the Web Display page), this is the simplest of iOS and H5 interaction. Now more and more mixed programming, H5 relatively speaking, so the study of JavaScriptCore framework is quite necessary. Okay, no, it's useless. To engage in today's theme---javascriptcore framework, first of all to say javascriptcore framework of several commonly used classes.
Class description for JavaScriptCore
Before we do the interaction between OC and H5, we need to import the JavaScriptCore framework first.
#import <JavaScriptCore/JavaScriptCore.h>
Then we enter the JavaScriptCore.h of the JavaScriptCore framework, and we find a total of several classes as follows.
- Jscontextjscontext represents an instance of a JavaScript execution environment. All JavaScript execution is done within the context. Jscontext is also used to manage the virtual machine (API document translation) of JavaScript in the life cycle of the object. As a context in many places we are likely to use, such as coredata,coregraphics and so on, so what is the context object exactly? You can understand that it is a bridge between the two.
- The main function of Jsvaluejsvalue is to receive jscontext execution of the return results, of course, jsvalue can be any type of JS, for example, JS variables, objects and functions. Let's give an example to illustrate For example, we now need to receive a variable from the Jscontext object. We can look at the following.
First, we define a string variable in the <script> tag. <script type="text/javascript"> var myObject = "myObject"; </script>
Then we represent the following in the OC Code, where Self.context represents the Jscontext object that has already been initialized. self.context[@"myObject"];
Of course, if we need to use the Jsvalue object in OC, then we may need to convert his type appropriately, and the framework provides a number of ways. For example, we want to print it as shown below. NSLog(@"%@",[myObject toString]);
- Jsmanagedvaluejsmanagedvalue This class in fact, I have not specifically used it. I'm going to have to explain this to the API documentation. Jsmanagedvalue is a Jsvalue package that solves the problem of circular referencing between JS and OC code. , the most common use of jsmanagedvalue is to safely refer to Jsvalue objects from within the memory heap. If the jsvalue is stored in the memory heap in a way that is incorrect, it can easily cause a circular reference and then cause the Jscontext object to not be released correctly.
- Jsvirtualmachine a Jsvirtualmachine object actually represents a JavaScript object space or a set of execution resources. Jsvirtualmachine Support line Shuo full lock, virtual machine, concurrent allocation of supported JavaScript execution. It's also said that Jsvirtualmachine is used to manage the entire JavaScript, and of course, I have not used this class.
Initialization of Jscontext objects in JavaScriptCore
Before iOS interacts with H5, what we need to do is to initialize the Jscontext object with the entire WebView -(void) Webviewdidfinishload: (UIWebView *) WebView this proxy method. So we need to initialize the WebView and set up proxies, and there's not much to say. Let's just look at how the Jscontext object is initialized in the proxy method. The code is shown below.
- (void)webViewDidFinishLoad:(UIWebView *)webView{ //对JSContext对象进行初始化 self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; //验证JSContext对象是否初始化成功 self.context.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) { context.exception = exceptionValue; };}
JavaScript to extract OC code
Previous module We have initialized the Jscontext object, so there are two main ways to use JavaScript to get the OC code, one is to use block (simple brute), and the other is to use the Jsexport protocol (winning thousands).
- Block mode
Block mode is relatively simple, but also I recommend a price, but should pay attention to prevent the occurrence of circular reference problems. First, let's talk about function calls without arguments, that is, we don't need to have parameter values from the page, such as jump pages and so on. The code is shown below.
The button code for the <body> tag in the HTML file
<button onclick="myAction();" style="">点击按钮返回上一个页面</button>
The Block - (void)webViewDidFinishLoad:(UIWebView *)webView
block code is implemented in OC in the method.
__weak typeof(self)temp = self; self.context[@"myAction"] = ^(){ [temp.navigationController popViewControllerAnimated:YES]; };
Let's take a look at the value of the page, we pass the value of the H5 tag as a parameter, and call OC block for printing.
The DIV tag code for the <body> tag in the HTML file (one input box, one button)
<input type="text" name="输入框" id="textField" placeholder="请输入要打印的信息" /> <button onclick="log(document.getElementById(‘textField‘).value);">打印输入框信息</button>
Then we implement the following block function in the OC code. where the string parameter is the value of the input box in the Web page.
self.context[@"log"] = ^(NSString *string){ NSLog(@"%@",string); };
As shown below. The coordinates are the phone simulator and the right side is the Xcode console.
- Jsexport protocol by implementing the Jsexport protocol to the OC and JS interaction, here I simply implement the following function calls without parameters. First, we create a button in the HTML file to invoke the Jsexport protocol method in OC.
<button onclick="native.myLog();">调用OC中myLog方法</button>
We need to designate the native object as the current controller, which is itself. This code is in- (void)webViewDidFinishLoad:(UIWebView *)webView
Implemented in the method. self.context[@"native"] = self;
Then we're going to write a protocol that inherits from Jsexport, and the protocol is as follows. I'm going to do some explaining about this macro definition for Jsexportas (propertyname,selector), which means that PropertyName represents the name of the JS function. While selector represents the OC protocol approach, it is important to note that selector must have parameters, whether or not it is necessary to pass a value. (I do not know why.??, ask God to explain)@protocol WebExport <JSExport>JSExportAs(myLog ,- (void)myOCLog :(NSString *)string);@end
After defining the method, we let the current controller adhere to the Protocol. Implements the proxy method.@interface JavaScriptCallOCViewController ()<UIWebViewDelegate,WebExport>
- (void)myOCLog :(NSString *)string{ NSLog(@"你好,世界!");}
OC Call JavaScript function
iOS talk about webview a usage of JS. (Get rid of ads for Web display pages) We said a simple way to get the JavaScript function through OC, of course, we just stringByEvaluatingJavaScriptFromString
added a JS statement using the method. The code looks like this. You can view the original text.
- (void)webViewDidFinishLoad:(UIWebView *)webView{ [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.getElementsByClassName(‘adpic‘)[0].style.display = ‘none‘"];}
Today we'll talk about how to use JavaScriptCore to let OC invoke JavaScript functions, The use of JavaScriptCore for OC calls to JavaScript functions is easy to perform. First we need to create a love in the HTML file for you a tag with an ID and a JavaScript function. The code is shown below.
<b id="label">需要改变的标签</b>
<script type="text/javascript"> function labelAction(obj) { document.getElementById(‘label‘).innerHTML = obj; } </script>
Then there is the operation in the OC code, and we still need to initialize the WebView and Jscontext objects first. There's no repetition here.
To demonstrate the effect, I put the call of the function in the Rightbarbuttonitem method. The overall code is shown below.
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"改变" style:UIBarButtonItemStyleDone target:self action:@selector(changeWebTxet)];
The following is the implementation method, first we have to obtain the corresponding function in JS through the Jscontext object and use the Jsvalue object to receive. Then we use the JS - (JSValue *)callWithArguments:(NSArray *)arguments;
function to make the call, of course, the JS function here does not return the value, I did not do to receive the return value of the work .
-(void)changeWebTxet{ JSValue *labelAction = self.context[@"labelAction"]; [labelAction callWithArguments:@[@"你好,JS世界!"]];}
Let's look at the overall implementation effect.
End
Preliminary trial of JavaScriptCore frame the personal feeling is still very good, the javascriptcore frame is easy to get started with. Of course, there is a certain understanding and foundation for JavaScript, so it's easier to learn. If you have any questions, welcome to the House of Sao, Finally, I enclose the implementation of this document demo.
JavaScript: Talking about the interactive-javascriptcore framework between iOS and H5