WebViewJavascriptBridge source code exploration-view the interaction process between OC and JS and between wkwebviewjs oc

Source: Internet
Author: User
Tags convert json to string

WebViewJavascriptBridge source code exploration-view the interaction process between OC and JS and between wkwebviewjs oc

Today, I checked the source code of the third-party library WebViewJavascriptBridge that implements interaction between OC code and JS Code. We know that oc calls js methods. The system provides the stringByEvaluatingJavaScriptFromString function.

. Now I want to know how js calls the oc method and share the exploration process.

There are not many source code, just the header file WebViewJavascriptBridge. h and the implementation file WebViewJavascriptBridge. m, and a js file, so that you can call the oc method on the js side or the js method on the oc side.

First, implement a simple demo of mutual calling between oc and js, and append the scenario of mutual calling between oc and js used in the simulation project:

  

 

I. Then let's talk about how js calls the oc method. How are they implemented? Three library files

 

We track the process of loading UIWebView by the oc controller and the process of calling the oc method by js.

 

Contains the initial js Code.

In this js file, a WebViewJavascriptBridge script object is created, and a hidden iframe tag is created. Each time JavaScript calls the oc method, the src of the iframe tag is modified to trigger the proxy listening method of UIWebView.

; (Function () {if (window. webViewJavascriptBridge) {return} var messagingIframe var sendMessageQueue = [] var receiveMessageQueue = [] var messageHandlers = {} var response = 'hangzhou' var QUEUE_HAS_MESSAGE = '_ callback _' var responseCallbacks = {} var uniqueId = 1 function _ createQueueReadyIframe (doc) {messagingIframe = doc. createElement ('iframe') messagingIframe. st Yle. display = 'none' messagingIframe. src = CUSTOM_PROTOCOL_SCHEME + ': //' + QUEUE_HAS_MESSAGE doc.doc umentElement. appendChild (messagingIframe)} function init (messageHandler) {if (WebViewJavascriptBridge. _ messageHandler) {throw new Error ('webviewjavascriptbridge. init called twice ')} WebViewJavascriptBridge. _ messageHandler = messageHandler var receivedMessages = receiveMessageQueue receivemesages EQueue = null for (var I = 0; I <receivedMessages. length; I ++) {_ dispatchMessageFromObjC (receivedMessages [I])} function send (data, responseCallback) {_ doSend ({data: data}, responseCallback )} function registerHandler (handlerName, handler) {messageHandlers [handlerName] = handler} function callHandler (handlerName, data, responseCallback) {_ doSend ({handlerName: handlerName, data: data}, respons ECallback)} function _ doSend (message, responseCallback) {if (responseCallback) {var callbackId = 'cb _ '+ (uniqueId ++) +' _ '+ new Date (). getTime () responseCallbacks [callbackId] = responseCallback message ['callbackid'] = callbackId} sendMessageQueue. push (message); // put the dictionary into an array // modify the src attribute of the iframe tag, and the UIWebView listener executes the proxy method messagingIframe. src = CUSTOM_PROTOCOL_SCHEME + ': //' + QUEUE_HAS_MESSAGE;} function _ fetch Queue () {// convert the json array to the json string var messageQueueString = JSON. stringify (sendMessageQueue) sendMessageQueue = [] return messageQueueString} function _ dispatchMessageFromObjC (messageJSON) {setTimeout (function _ timeoutDispatchMessageFromObjC () {var message = JSON. parse (messageJSON) var messageHandler if (message. responseId) {var responseCallback = responseCallbacks [message. responseId] if (! ResponseCallback) {return;} responseCallback (message. responseData) delete responseCallbacks [message. responseId]} else {var responseCallback if (message. callbackId) {var callbackResponseId = message. callbackId responseCallback = function (responseData) {_ doSend ({responseId: callbackResponseId, responseData: responseData})} var handler = WebViewJavascriptBridge. _ messageHandler if (message. han DlerName) {handler = messageHandlers [message. handlerName]} try {handler (message. data, responseCallback)} catch (exception) {if (typeof console! = 'Undefined') {console. log ("WebViewJavascriptBridge: WARNING: javascript handler threw. ", message, exception) }}} function _ handleMessageFromObjC (messageJSON) {if (receiveMessageQueue) {receiveMessageQueue. push (messageJSON)} else {_ dispatchMessageFromObjC (messageJSON)} window. webViewJavascriptBridge = {init: init, send: send, registerHandler: registerHandler, callHandler: callHandler, _ fetchQueue: _ fetchQueue, _ blank: _ blank} var doc = document _ blank (doc) var readyEvent = doc. createEvent ('events') readyEvent. initEvent ('webviewjavascriptbridgeready') readyEvent. bridge = WebViewJavascriptBridge doc. dispatchEvent (readyEvent )})();View Code

 

2. uiwebview.pdf the custom HTML page testjsbridge.html contains the script to register the oc method ID for js call and the js ID for oc call.

<Html>  

3. Click the html Tag button to trigger the js event.

// Set the event var callbackButton = document for the tag button. getElementById ('jsbtn '); callbackButton. onclick = function (e) {e. preventDefault (); // register the js_Call_Objc_Func ID to facilitate js to send messages to IOS bridge. callHandler ('js _ Call_Objc_Func ', {id: 1, info: 'Hello, iOS, I'm coming from the js side! '}, Function (response ){});}

We track the bridge. callHandler method and enter WebViewJavascriptBridge. js.

Var CUSTOM_PROTOCOL_SCHEME = 'wvjbscheme'

Var QUEUE_HAS_MESSAGE = '_ WVJB_QUEUE_MESSAGE __'

MessagingIframe is an iframe tag. Click the custom html button tag to trigger the js event and enter callHandler --> _ doSend,

When the messagingIframe label src is re-assigned, the proxy method of UIWebView is triggered (the src value is always: wvjbscheme: // _ WVJB_QUEUE_MESSAGE _, which can also be customized, this will be used as an identifier for determining when you enter the oc UIWebView proxy method ).

Follow up the subsequent execution process:

  

So far, js has successfully called oc

Summarize the process of js calling oc:

--> Trigger js events

--> Store the "js_Call_Objc_Func" parameter to the js array sendMessageQueue.

--> Re-assign the src attribute of the iframe tag, trigger the UIWebView proxy method, and enter the corresponding processing method according to the src value.

--> Call js method _ fetchQueue In the oc method to obtain all parameters in the js array.

--> Based on the imported custom registration ID js_Call_Objc_Func, find the matching block from the oc dictionary _ messageHandlers, and finally execute the block, which contains the subsequent code for custom processing.

 

Ii. js call process by oc

Initiated from within oc

--> Call the callHandler method of bridge to pass in the required parameters and custom registration ID

--> Finally, use the UIWebView system method stringByEvaluatingJavaScriptFromString to call the js script WebViewJavascriptBridge. _ handleMessageFromObjC to pass parameters.

--------------------------------------------- End --------------------------------------

Download DEMO

Github address: https://github.com/xiaotanit/Tan_WebViewJavaScriptBridge

 

In addition, the following url issue is recorded:

Assume the loaded url is: http://baidu.com /? Search = blog

In this way, the url with Chinese parameters loaded by UIWebView cannot be displayed. You must escape Chinese characters to display the url.

Use the string method stringByAddingPercentEncodingWithAllowedCharacters to escape Chinese characters.

NSString * str = @ "The http://baidu.com /? Search = blog "; // str = [str stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; str = [str character: [NSCharacterSet characterSetWithCharactersInString: @ "'# % ^ {}\" [] |\<> "]. invertedSet];
NSURL * url = [NSURL URLWithString: str];

NSURLRequest * request = [NSURLRequest requestWithURL: url];

 

Link: http://www.cnblogs.com/tandaxia/p/5699886.html

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.