WebViewJavascriptBridge source code, javascriptbridge
WebViewJavascriptBridge is an open-source framework that connects javascript and iOS Native interaction. It can be used to respond to events and execute Native methods in UIWebview, or call javascript methods using Native methods, as its name suggests, it seems that the bridge has been connected to both ends.
First, let's take a look at how to use it. After you drag it through cocopods or directly into the project, introduce the header file WebViewJavascriptBridge. h. The method provided by it is relatively simple and easy to use.
Native end
First, the initialization method is as follows:
- (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView handler:(WVJBHandler)handler; - (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler; - (instancetype)bridgeForWebView:(WVJB_WEBVIEW_TYPE*)webView webViewDelegate:(WVJB_WEBVIEW_DELEGATE_TYPE*)webViewDelegate handler:(WVJBHandler)handler resourceBundle:(NSBundle*)bundle;
- WebView:
- Handler: callback block, which returns the data returned by javascript
- WebViewDelegate: the proxy object of our webView. It is the object for processing the webView event.
- Bundle: the bundle of the WebViewJavascriptBridge. js. text file. It will be found in the webView callback.
Then we can use
- (void)send:(id)message;- (void)send:(id)message responseCallback:(WVJBResponseCallback)responseCallback;
Method to send data to javascript. javascript receives the data when executing init, which can be the data to be displayed by webView. message can be customized. The data needs to be parsed and used in javascript. responseCallback is the callback method after receiving the data.
Finally, we use
- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler;
Register some methods. handlerName is the agreed string. These registration methods are called by javascript. Native receives and processes the response in handler.
We can also send messages to javascript
- (void)callHandler:(NSString*)handlerName;- (void)callHandler:(NSString*)handlerName data:(id)data;- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;
Now that Navtive is configured, what the javascript end needs to do is to add a javascript method.
function connectWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) } else { document.addEventListener('WebViewJavascriptBridgeReady', function() { callback(WebViewJavascriptBridge) }, false) }}
The method will initialize a WebViewJavascriptBridge object only once. Then, in javascript, you can use this object method to send and receive messages.
ConnectWebViewJavascriptBridge (function (bridge) {/* Init your app here * // initialize bridge. init (function (message, responseCallback) {alert ('Received message: '+ message) if (responseCallback) {responseCallback ("Right back atcha ")}}) // send the message to Native bridge. send ('Hello from the javascript ') bridge. send ('Please respond to this ', function responseCallback (responseData) {console. log ("Javascript got its response", responseData)}) // register the message and accept the message bridge from Native. registerHandler ('setfontevent', function (data, responseCallback) {setFontSize (data )})
So how is WebViewJavascriptBridge implemented internally?
The source file consists of two parts: WebViewJavascriptBridge. h and. m iOS, and WebViewJavascriptBridge.js.txt javascript.
There are three set objects in WebViewJavascriptBridge. m.
// Store NSMutableArray * _ startupMessageQueue from Native; // store callback blocks implemented by Native * _ responseCallbacks; // store Native and javascript-agreed message names NSMutableDictionary * _ messageHandlers;
When the bridge is initialized, bridge registers the webView proxy to itself and implements several proxy methods of UIWebview for message processing.
When webView registers a message with bridge, bridge stores the message name key and the callback Block value in _ messageHandlers.
When webView sends a message to javascript, it callssend:OrcallHandler:A message dictionary is built internally to store the sent data, callback blocks, message IDs, and method names, similar to the following structure: {'data': data, 'callbackid': objc_cb_1, 'handlername': handlerName} Where ID is the auto-incrementing ID objc_cb_1, 2, 3 .. in addition, the _ responseCallbacks is used to save an ID and a callback block. the constructed message dictionary is added to _ startupMessageQueue to wait for the message to be sent to javascript.
How are these messages distributed?
Bridge is the proxy method in UIWebviewwebViewDidFinishLoadWhen the webView load is complete, it will call the method to traverse _ startupMessageQueue, where the message dictionary with distribution is stored and each message dictionary is called.- (void)_dispatchMessage:(WVJBMessage*)messageA javascript method is executed for sending and distributing messages.WebViewJavascriptBridge._dispatchMessageFromObjC(data)This method is defined in WebViewJavascriptBridge.js.txt, which also implements the same logic as WebViewJavascriptBridge. m, and then calls the javascript method to achieve message transmission.
So how does javascript pass messages to Native?
Of course, it is also passed through the proxy method of UIWebview.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
This method will be called before loading webView and asked whether to load it. It can capture the uiwebview request. therefore, bridgereceives the javascript method call in webviewjavascriptbridge.js.txt and sets the HTML IFrame. A request is sent:messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGEThis will trigger the UIWebviewshouldStartLoadWithRequestMethod. In this method, bridge parses parameters according to the custom format and extracts the stored callback block from _ responseCallbacks for callback.
In this way, the communication between javascript and Native is completed.