{"id":1035,"date":"2014-01-02T18:36:54","date_gmt":"2014-01-02T13:06:54","guid":{"rendered":"http:\/\/ramkulkarni.com\/blog\/?p=1035"},"modified":"2014-01-02T18:36:54","modified_gmt":"2014-01-02T13:06:54","slug":"framework-for-interacting-with-embedded-webview-in-ios-application","status":"publish","type":"post","link":"http:\/\/ramkulkarni.com\/blog\/framework-for-interacting-with-embedded-webview-in-ios-application\/","title":{"rendered":"Framework for interacting with embedded WebView in iOS application"},"content":{"rendered":"<p>Last year around the same time I had written a post about\u00a0<a title=\"Calling Objective-C code from JavaScript in iOS applications\" href=\"http:\/\/ramkulkarni.com\/blog\/calling-objective-c-function-from-javascript-in-ios-applications\/\">Calling Objective-C code from JavaScript in iOS applications<\/a>\u00a0. I created a simple framework for it and described how to use it in that post.<\/p>\n<p>Recently I was working on an application that required WebView to be embedded in the same View Controller along with other native iOS controls. I decided to use the above framework, but knew that \u00a0my ViewController class will have to extend <a href=\"http:\/\/ramkulkarni.com\/temp\/2013-01-12\/WebViewController.h\" target=\"_blank\">WebViewController<\/a> class of the framework. Though I could have done that, I thought separating the functionality of <a href=\"https:\/\/developer.apple.com\/library\/ios\/documentation\/uikit\/reference\/UIWebViewDelegate_Protocol\/Reference\/Reference.html\" target=\"_blank\">UIWebViewDelegate<\/a> from the WebViewController would be a better design. So I replaced WebViewController with WebViewDelegate which implements UIWebViewDelegate protocol. I also removed\u00a0getInitialPageName method from\u00a0<a href=\"http:\/\/ramkulkarni.com\/temp\/2013-01-12\/WebViewInterface.h\" target=\"_blank\">WebViewInterface.h<\/a>\u00a0. So here are the files in the new framework &#8211;<!--more--><\/p>\n<p><a href=\"http:\/\/ramkulkarni.com\/temp\/2014-01-02\/WebViewDelegate.h\" target=\"_blank\">WebViewDelegate.h<\/a><br \/>\n<a href=\"http:\/\/ramkulkarni.com\/temp\/2014-01-02\/WebViewDelegate.m\" target=\"_blank\">WebViewDelegate.m<\/a><br \/>\n<a href=\"http:\/\/ramkulkarni.com\/temp\/2014-01-02\/WebViewInterface.h\" target=\"_blank\">WebViewInterface.h<br \/>\n<\/a><a href=\"http:\/\/ramkulkarni.com\/temp\/2014-01-02\/iosBridge.js\" target=\"_blank\">iosBridge.js<\/a><\/p>\n<p>To explain how to use this framework, I will take a simple example where a ViewController contains mix of native controls and a WebView (BTW, because delegate functionality is separated from the ViewController, you can now have multiple Web Views in the same View Controller and can still use the framework). Let&#8217;s create a ViewController that has a text box and a button (native controls) and a WebView.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1036\" data-permalink=\"http:\/\/ramkulkarni.com\/blog\/framework-for-interacting-with-embedded-webview-in-ios-application\/20140102_app1\/\" data-orig-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2014\/01\/20140102_App1.png?fit=368%2C716\" data-orig-size=\"368,716\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"20140102_App1\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2014\/01\/20140102_App1.png?fit=154%2C300\" data-large-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2014\/01\/20140102_App1.png?fit=368%2C716\" class=\"size-medium wp-image-1036 alignleft\" style=\"font-size: 12px;\" alt=\"20140102_App1\" src=\"https:\/\/i0.wp.com\/138.197.85.232\/blog\/wp-content\/uploads\/2014\/01\/20140102_App1-154x300.png?resize=154%2C300\" width=\"154\" height=\"300\" srcset=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2014\/01\/20140102_App1.png?resize=154%2C300 154w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2014\/01\/20140102_App1.png?w=368 368w\" sizes=\"(max-width: 154px) 100vw, 154px\" data-recalc-dims=\"1\" \/>The WebView contains a combo box. There is no native combo box control in the Cocoa library, so this example might be useful to you if you want to create a combo box and don&#8217;t mind if it is created using HTML.<\/p>\n<p>When the view controller is loaded, it opens index.html in the web view. index.html has just one combo box and it calls a native (Objective-C) method to get the content and populates the list. If you enter text in the text box and click add button, the native code calls a method in JavaScript in index.html to add new item to the list.<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/138.197.85.232\/blog\/wp-content\/uploads\/2014\/01\/20140102_Storyboard.png\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1037\" data-permalink=\"http:\/\/ramkulkarni.com\/blog\/framework-for-interacting-with-embedded-webview-in-ios-application\/20140102_storyboard\/\" data-orig-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2014\/01\/20140102_Storyboard.png?fit=321%2C334\" data-orig-size=\"321,334\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"20140102_Storyboard\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2014\/01\/20140102_Storyboard.png?fit=288%2C300\" data-large-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2014\/01\/20140102_Storyboard.png?fit=321%2C334\" class=\" wp-image-1037 alignleft\" alt=\"20140102_Storyboard\" src=\"https:\/\/i0.wp.com\/138.197.85.232\/blog\/wp-content\/uploads\/2014\/01\/20140102_Storyboard-288x300.png?resize=161%2C168\" width=\"161\" height=\"168\" srcset=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2014\/01\/20140102_Storyboard.png?resize=288%2C300 288w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2014\/01\/20140102_Storyboard.png?w=321 321w\" sizes=\"(max-width: 161px) 100vw, 161px\" data-recalc-dims=\"1\" \/><\/a><\/p>\n<p>This is how the storyboard for this app looks like. Text box, add button and WebView are native iOS controls. Combo box is HTML control displayed in the WebView.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>I created a ViewController class for the above view and called it RKMainViewController.<br \/>\n<!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #bc7a00;\">#import &lt;UIKit\/UIKit.h&gt;<\/span>\n<span style=\"color: #bc7a00;\">#import \"WebViewInterface.h\"<\/span>\n\n<span style=\"color: #008000; font-weight: bold;\">@interface<\/span> <span style=\"color: #0000ff; font-weight: bold;\">RKMainViewController<\/span> : <span style=\"color: #0000ff; font-weight: bold;\">UIViewController<\/span> <span style=\"color: #666666;\">&lt;<\/span>WebViewInterface<span style=\"color: #666666;\">&gt;<\/span>\n<span style=\"color: #008000; font-weight: bold;\">@property<\/span> (weak, nonatomic) <span style=\"color: #b00040;\">IBOutlet<\/span> UIWebView <span style=\"color: #666666;\">*<\/span>webView;\n\n<span style=\"color: #008000; font-weight: bold;\">@end<\/span><\/pre>\n<\/div>\n<p>So unlike the previous framework, this class does not extend WebViewController. It extends UIViewController and implements <a href=\"http:\/\/ramkulkarni.com\/temp\/2014-01-02\/WebViewInterface.h\" target=\"_blank\">WebViewInterface<\/a> protocol of the framework. I have also created an outlet for the web view.<\/p>\n<p>In the implementation of this class (RKMainViewController.m), I first declare local property (for <a href=\"http:\/\/ramkulkarni.com\/temp\/2014-01-02\/WebViewDelegate.h\" target=\"_blank\">WebViewDelegate<\/a>) , action for &#8216;Add&#8217; button and outlet for text box.<!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000; font-weight: bold;\">@interface<\/span> <span style=\"color: #0000ff; font-weight: bold;\">RKMainViewController<\/span> ()\n\t<span style=\"color: #008000; font-weight: bold;\">@property<\/span> (weak, nonatomic) <span style=\"color: #b00040;\">IBOutlet<\/span> UITextField <span style=\"color: #666666;\">*<\/span>txt1;\n\t<span style=\"color: #666666;\">-<\/span> (<span style=\"color: #b00040;\">IBAction<\/span>)onAdd<span style=\"color: #666666;\">:<\/span>(<span style=\"color: #b00040;\">id<\/span>)sender;\n\t<span style=\"color: #008000; font-weight: bold;\">@property<\/span> WebViewDelegate <span style=\"color: #666666;\">*<\/span>webViewDelegate;\n<span style=\"color: #008000; font-weight: bold;\">@end<\/span><\/pre>\n<\/div>\n<p>Of course, you need to connect outlet and action to controls in the storyboard. In the viewLoad function of this class, I create a new instance of WebViewDelegate, disable scrolling on it and load index.html from www folder &#8211;<!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000; font-weight: bold;\">-<\/span> (<span style=\"color: #b00040;\">void<\/span>)<span style=\"color: #0000ff;\">viewDidLoad<\/span>\n{\n    [super viewDidLoad];\n\n\tself.webViewDelegate <span style=\"color: #666666;\">=<\/span> [[WebViewDelegate alloc] initWithWebView<span style=\"color: #666666;\">:<\/span>self.webView withWebViewInterface<span style=\"color: #666666;\">:<\/span>self];\n\n\tself.webView.scrollView.scrollEnabled <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000;\">false<\/span>;\n\t[self.webViewDelegate loadPage<span style=\"color: #666666;\">:<\/span><span style=\"color: #ba2121;\">@\"index.html\"<\/span> fromFolder<span style=\"color: #666666;\">:<\/span><span style=\"color: #ba2121;\">@\"www\"<\/span>];\n}<\/pre>\n<\/div>\n<p>processFunctionFromJS (part of <a href=\"http:\/\/ramkulkarni.com\/temp\/2014-01-02\/WebViewInterface.h\" target=\"_blank\">WebViewInterface<\/a> protocol. RKMainViewController implements this protocol. See the class declaration above) function is where we handle methods called from JavaScript. In this example I handle &#8216;loadList&#8217; function called from JS &#8211;<!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000; font-weight: bold;\">-<\/span> (<span style=\"color: #b00040;\">id<\/span>) <span style=\"color: #0000ff;\">processFunctionFromJS:<\/span>(NSString <span style=\"color: #666666;\">*<\/span>) name withArgs<span style=\"color: #666666;\">:<\/span>(NSArray<span style=\"color: #666666;\">*<\/span>) args error<span style=\"color: #666666;\">:<\/span>(NSError <span style=\"color: #666666;\">**<\/span>) error\n{\n\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> ([name compare<span style=\"color: #666666;\">:<\/span><span style=\"color: #ba2121;\">@\"loadList\"<\/span> options<span style=\"color: #666666;\">:<\/span>NSCaseInsensitiveSearch] <span style=\"color: #666666;\">==<\/span> NSOrderedSame)\n\t{\n\t\tNSArray <span style=\"color: #666666;\">*<\/span>listElements <span style=\"color: #666666;\">=<\/span> <span style=\"border: 1px solid #FF0000;\">@<\/span>[<span style=\"color: #ba2121;\">@\"Item 1\"<\/span>, <span style=\"color: #ba2121;\">@\"Item 2\"<\/span>];\n\n\t\tNSData <span style=\"color: #666666;\">*<\/span>jsonData <span style=\"color: #666666;\">=<\/span> [NSJSONSerialization dataWithJSONObject<span style=\"color: #666666;\">:<\/span>listElements options<span style=\"color: #666666;\">:0<\/span> error<span style=\"color: #666666;\">:<\/span><span style=\"color: #008000;\">nil<\/span>];\n\n\t\tNSString <span style=\"color: #666666;\">*<\/span>result <span style=\"color: #666666;\">=<\/span> [[NSString alloc] initWithData<span style=\"color: #666666;\">:<\/span>jsonData encoding<span style=\"color: #666666;\">:<\/span>NSUTF8StringEncoding];\n\n\t\t<span style=\"color: #008000; font-weight: bold;\">return<\/span> result;\n\t}\n\n\t<span style=\"color: #008000; font-weight: bold;\">return<\/span> <span style=\"color: #008000;\">nil<\/span>;\n}<\/pre>\n<\/div>\n<p>I am returning two hard-coded list items in response to the call to loadList function. The result is returned as JSON string.<\/p>\n<p>Action handler for &#8216;Add&#8217; button gets text from the text box and calls JS function &#8216;addToList&#8217;.<!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000; font-weight: bold;\">-<\/span> (<span style=\"color: #b00040;\">IBAction<\/span>)<span style=\"color: #0000ff;\">onAdd:<\/span>(<span style=\"color: #b00040;\">id<\/span>)<span style=\"color: #19177c;\">sender<\/span> {\n\tNSDictionary <span style=\"color: #666666;\">*<\/span>dict <span style=\"color: #666666;\">=<\/span> <span style=\"border: 1px solid #FF0000;\">@<\/span>{<span style=\"color: #ba2121;\">@\"newListItem\"<\/span><span style=\"color: #666666;\">:<\/span>self.txt1.text};\n\n\t[self.webViewDelegate callJSFunction<span style=\"color: #666666;\">:<\/span><span style=\"color: #ba2121;\">@\"addToList\"<\/span> withArgs<span style=\"color: #666666;\">:<\/span>dict];\n\n}<\/pre>\n<\/div>\n<p>Text to be added is passed in a dictionary, with key &#8216;newListItem&#8217;.<\/p>\n<p>Now, let&#8217;s look at index.html. JS code in this file \u00a0calls loadList function to populate the combo list and declares &#8216;addToList&#8217; JS function, which is called from the native code, as shown in the code snippet above.<!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000; font-weight: bold;\">&lt;script <\/span><span style=\"color: #7d9029;\">src=<\/span><span style=\"color: #ba2121;\">\"iosBridge.js\"<\/span><span style=\"color: #008000; font-weight: bold;\">&gt;&lt;\/script&gt;<\/span>\n\n<span style=\"color: #008000; font-weight: bold;\">&lt;script&gt;<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">function<\/span> onErrorCallingNativeFunction (err)\n\t{\n\t\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> (err)\n\t\t{\n\t\t\talert(err.message);\n\t\t}\n\t}\n\n\t<span style=\"color: #008000; font-weight: bold;\">function<\/span> onReady()\n\t{\n\t\tcalliOSFunction(<span style=\"color: #ba2121;\">\"loadList\"<\/span>, [],<span style=\"color: #008000; font-weight: bold;\">function<\/span>(ret){\n\t\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> listValues <span style=\"color: #666666;\">=<\/span> JSON.parse(ret.result);\n\t\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> selectElm <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000;\">document<\/span>.getElementById(<span style=\"color: #ba2121;\">\"select1\"<\/span>);\n\t\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> options <span style=\"color: #666666;\">=<\/span> <span style=\"color: #ba2121;\">\"\"<\/span>;\n\t\t\t<span style=\"color: #008000; font-weight: bold;\">for<\/span> (<span style=\"color: #008000; font-weight: bold;\">var<\/span> i <span style=\"color: #666666;\">=<\/span> <span style=\"color: #666666;\">0<\/span>; i <span style=\"color: #666666;\">&lt;<\/span> listValues.length; i<span style=\"color: #666666;\">++<\/span>)\n\t\t\t{\n\t\t\t\toptions <span style=\"color: #666666;\">+=<\/span> <span style=\"color: #ba2121;\">\"&lt;option value='\"<\/span> <span style=\"color: #666666;\">+<\/span> listValues[i] <span style=\"color: #666666;\">+<\/span> <span style=\"color: #ba2121;\">\"'&gt;\"<\/span> <span style=\"color: #666666;\">+<\/span> listValues[i] <span style=\"color: #666666;\">+<\/span> <span style=\"color: #ba2121;\">\"&lt;\/option&gt;\"<\/span>;\n\t\t\t}\n\t\t\tselectElm.innerHTML <span style=\"color: #666666;\">=<\/span> options;\n\t\t}, onErrorCallingNativeFunction);\n\n\t}\n\n\t<span style=\"color: #008000; font-weight: bold;\">function<\/span> addToList(dataObj)\n\t{\n\t\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> (dataObj <span style=\"color: #666666;\">!==<\/span> <span style=\"color: #008000; font-weight: bold;\">undefined<\/span> <span style=\"color: #666666;\">&amp;&amp;<\/span> <span style=\"color: #008000; font-weight: bold;\">typeof<\/span> dataObj.newListItem <span style=\"color: #666666;\">!==<\/span> <span style=\"color: #ba2121;\">'undefined'<\/span>)\n\t\t{\n\t\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> selectElm <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000;\">document<\/span>.getElementById(<span style=\"color: #ba2121;\">\"select1\"<\/span>);\n\t\t\tselectElm.innerHTML <span style=\"color: #666666;\">+=<\/span> <span style=\"color: #ba2121;\">\"&lt;option value='\"<\/span> <span style=\"color: #666666;\">+<\/span> dataObj.newListItem <span style=\"color: #666666;\">+<\/span> <span style=\"color: #ba2121;\">\"' selected&gt;\"<\/span> <span style=\"color: #666666;\">+<\/span> dataObj.newListItem <span style=\"color: #666666;\">+<\/span> <span style=\"color: #ba2121;\">\"&lt;\/option&gt;\"<\/span>;\n\t\t}\n\t}\n\n<span style=\"color: #008000; font-weight: bold;\">&lt;\/script&gt;<\/span>\n\n<span style=\"color: #008000; font-weight: bold;\">&lt;body<\/span> <span style=\"color: #7d9029;\">onload=<\/span><span style=\"color: #ba2121;\">\"onReady();\"<\/span><span style=\"color: #008000; font-weight: bold;\">&gt;<\/span>\n\n<span style=\"color: #008000; font-weight: bold;\">&lt;select<\/span> <span style=\"color: #7d9029;\">id=<\/span><span style=\"color: #ba2121;\">\"select1\"<\/span> <span style=\"color: #7d9029;\">style=<\/span><span style=\"color: #ba2121;\">\"font-size:12pt;width:100%\"<\/span><span style=\"color: #008000; font-weight: bold;\">&gt;<\/span>\n<span style=\"color: #008000; font-weight: bold;\">&lt;\/select&gt;<\/span>\n\n<span style=\"color: #008000; font-weight: bold;\">&lt;\/body&gt;<\/span><\/pre>\n<\/div>\n<p>Notice that\u00a0calliOSFunction (declared in <a href=\"http:\/\/ramkulkarni.com\/temp\/2014-01-02\/iosBridge.js\" target=\"_blank\">iosBridge.js<\/a>) is called from onReady function, which is called when the HTML body is loaded. The first argument to &#8216;calliOSFunction&#8217; is the name of\u00a0native function to call (in this case &#8216;loadList&#8217;). The second argument is array of arguments to be passed to the native function and the last argument is callback function that the native code will call when result is ready.<br \/>\n<span style=\"font-size: 16px;\">Result is passed as JSON string to the callback function handler. So we first parse the string and create a JS object. In this case we know that result is an array of strings. So we iterate over the list and add items to the combo box.<\/span><\/p>\n<p>&#8216;addToList&#8217; function is called from the native code and takes JS object with the key-value pair. Expected key name is &#8216;newListItem&#8217; and value is string to be added to the list.<\/p>\n<p>In summary, this framework has a couple of advantages over the<a title=\"Calling Objective-C code from JavaScript in iOS applications\" href=\"http:\/\/ramkulkarni.com\/blog\/calling-objective-c-function-from-javascript-in-ios-applications\/\" target=\"_blank\"> one I had created earlier<\/a>, at the same time provides all the same functionality.<\/p>\n<ul>\n<li>Your view controller class need not extend the framework&#8217;s view controller class.<\/li>\n<li>It can support multiple web views in the same view controller.<\/li>\n<\/ul>\n<p>You can download entire source code for the above demo application from <a href=\"http:\/\/ramkulkarni.com\/temp\/2014-01-02\/WebDelegateDemo.zip\" target=\"_blank\">here<\/a>. The project is created with Xcode 5.0.<\/p>\n<p>-Ram Kulkarni<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last year around the same time I had written a post about\u00a0Calling Objective-C code from JavaScript in iOS applications\u00a0. I created a simple framework for it and described how to use it in that post. Recently I was working on an application that required WebView to be embedded in the same View Controller along with &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/ramkulkarni.com\/blog\/framework-for-interacting-with-embedded-webview-in-ios-application\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Framework for interacting with embedded WebView in iOS application&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[15,20,1],"tags":[87,14,5,63],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2g9O8-gH","jetpack-related-posts":[],"_links":{"self":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts\/1035"}],"collection":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/comments?post=1035"}],"version-history":[{"count":0,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts\/1035\/revisions"}],"wp:attachment":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/media?parent=1035"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/categories?post=1035"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/tags?post=1035"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}