We are going to learn about the following topics in the article:
(For more resources related to this topic, see here.)
Getting ready for iOS development
All of these code samples will be hosted as an Xcode project solution of some type on Packt Publishing’s website, but they will also be shown here if you want to follow along, without relying on code samples. Now with that said, lets get started…
iOS hybrid development
To install Xcode, we will need to start the installation process from the Mac App Store. Apple, in recent years, has moved its IDE to the Mac App Store for faster updates to developers and subsequently app updates for iOS and Mac applications. Installation is easy; simply log in with your Apple ID in the Mac App Store and download Xcode; you can search for it at the top or, if you look in the right rail among popular free downloads, you can find a link to the Xcode Mac App Store page. Once you reach this, click Install as shown in the following screenshot:
It’s important to know that, for the sake of simplicity in this article, we will not deploy an app to a device; so if you are curious about it, you will need to be actively enrolled in Apple’s Developer Program. The cost is 99 dollars a year, or 299 dollars for an enterprise license that allows deployment of an app outside the control of the iOS App Store.
If you’re curious to learn more about deploying to a device, the code in this article will run on the device assuming that your certificates are set up on your end.
For more information on this, check out Apple’s iOS Developer Center documentation online at https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40012582.
Once it’s installed, we can open up Xcode and look at the iOS Simulator; we can do this by clicking XCode, followed by Open Developer Tool, and then clicking on iOS Simulator. Upon first opening iOS Simulator, we will see what appears to be a simulation of an iOS device, shown in the next screenshot. Note that this is a simulation, not a real iOS device (even if it feels pretty close).
Setting up a simple iOS hybrid app
Now let’s create a simple web view, also known as a UIWebView, which is the class used to create a web view in an iOS app. First, let’s create a new iPhone project; we are using an iPhone to keep our app simple. Open Xcode and select the Create new XCode project project; then, as shown in the following screenshot, select the Single View Application option and click the Next button.
On the next view of the wizard, set the product name as JS_Performance, the language to Swift, and the device to iPhone; the organization name should autofill with your name based on your account name in the OS. The organization identifier is a reverse domain name unique identifier for our app; this can be whatever you deem appropriate. For instructional purposes, here’s my setup:
Once your project names are set, click the Next button and save to a folder of your choice with Git repository left unchecked. When that’s done, select Main.storyboard under your Project Navigator, which is found in the left panel. We should be in the storyboard view now. Let’s open the Object Library, which can be found in the lower-right panel in the subtab with an icon of a square inside a circle.
Search for Web View in the Object Library in the bottom-right search bar, and then drag that to the square view that represents our iOS view.
We need to consider two more things before we link up an HTML page using Swift; we need to set constraints as native iOS objects will be stretched to fit various iOS device windows. To fill the space, you can add the constraints by selecting the UIWebView object and pressing Command + Option + Shift + = on your Mac keyboard. Now you should see a blue border appear briefly around your UIWebView.
Lastly, we need to connect our UIWebView to our Swift code; for this, we need to open the Assistant Editor by pressing Command + Option + Return on the keyboard. We should see ViewController.swift open up in a side panel next to our Storyboard. To link this as a code variable, right-click (or option-click the UIWebView object) and, with the button held down, drag the UIWebView to line number 12 in the ViewController.swift code in our Assistant Editor. This is shown in the following diagram:
Once that’s done, a popup will appear. Now leave everything the same as it comes up, but set the name to webview; this will be the variable referencing our UIWebView. With that done, save your Main.storyboard file and navigate to your ViewController.swift file.
Now take a look at the Swift code shown in the following screenshot, and copy it into the project; the important part is on line 19, which contains the filename and type loaded into the web view; which in this case, this is index.html.
Now obviously, we don’t have an index.html file, so let’s create one. Go to File and then select New followed by the New File option. Next, under iOS select Empty Application and click Next to complete the wizard. Save the file as index.html and click Create. Now open the index.html file, and type the following code into the HTML page:
Now click Run (the play button in the main iOS task bar), and we should see our HTML page running inside our own app, as shown here:
That’s nice work! We built an iOS app with Swift (even if it’s a simple app). Let’s create a structured HTML page; we will override our Hello iOS text with the HTML shown in the following screenshot:
Here, we use the standard console.time function and print a message to our UIWebView page when finished; if we hit Run in Xcode, we will see the Loop Completed message on load. But how do we get our performance information? How can we get our console.timeEnd function code on line 14 on our HTML page?
Let’s check our project’s embedded HTML page console. First, open desktop Safari on your Mac and enable developer mode. Launch the Preferences option. Under the Advanced tab, ensure that the Show develop menu in menu bar option is checked, as shown in the following screenshot:
Next, let’s rerun our Xcode project, start up iOS Simulator and then rerun our page. Once our app is running with the Loop Completed result showing, open desktop Safari and click Develop, then iOS Simulator, followed by index.html.
If you look closely, you will see iOS simulator’s UIWebView highlighted in blue when you place the mouse over index.html; a visible page is seen as shown in the following screenshot:
Once we release the mouse on index.html, we Safari’s Web Inspector window appears featuring our hybrid iOS app’s DOM and console information. The Safari’s Web Inspector is pretty similar to Chrome’s Developer tools in terms of feature sets; the panels used in the Developer tools also exist as icons in Web Inspector.
Now let’s select the Console panel in Web Inspector. Here, we can see our full console window including our Timer console.time function test included in the for loop. As we can see in the following screenshot, the loop took 0.081 milliseconds to process inside iOS.
Comparing UIWebView with Mobile Safari
What if we wanted to take our code and move it to Mobile Safari to test? This is easy enough; as mentioned earlier in the article, we can drag-and-drop the index.html file into our iOS Simulator, and then the OS will open the mobile version of Safari and load the page for us.
With that ready, we will need to reconnect Safari Web Inspector to the iOS Simulator and reload the page. Once that’s done, we can see that our console.time function is a bit faster; this time it’s roughly 0.07 milliseconds, which is a full .01 milliseconds faster than UIWebView, as shown here:
We can also debug the app using the debugging inspector in the Safari’s Web Inspector tool. Click Debugger in the top menu panel in Safari’s Web Inspector. We can add a break point to our embedded script by clicking a line number and then refreshing the page with Command + R. In the following screenshot, we can see the break occurring on page load, and we can see our scope variable displayed for reference in the right panel:
We can also check page load times using the timeline inspector. Click Timelines at the top of the Web Inspector and now we will see a timeline similar to the Resources tab found in Chrome’s Developer tools. Let’s refresh our page with Command + R on our keyboard; the timeline then processes the page.
Common ways to improve hybrid performance
With hybrid apps, we can use all the techniques for improving performance using a build system such as Grunt.js or Gulp.js with NPM, using JSLint to better optimize our code, writing code in an IDE to create better structure for our apps, and helping to check for any excess code or unused variables in our code.
We can use best performance practices such as using strings to apply an HTML page (like the innerHTML property) rather than creating objects for them and applying them to the page that way, and so on.
Sadly, the fact that hybrid apps do not perform as well as native apps still holds true. Now, don’t let that dismay you as hybrid apps do have a lot of good features! Some of these are as follows:
- They are (typically) faster to build than using native code
- They are easier to customize
- They allow for rapid prototyping concepts for apps
- They are portable; they can be reused for another platform (with some modification) for Android devices, Windows Modern apps, Windows Phone apps, Chrome OS, and even Firefox OS
- They can interact with native code using helper libraries such as Cordova
At some point, however, application performance will be limited to the hardware of the device, and it’s recommended you move to native code. But, how do we know when to move? Well, this can be done using Color Blended Layers. The Color Blended Layers option applies an overlay that highlights slow-performing areas on the device display, for example, green for good performance and red for slow performance; the darker the color is, the more impactful will be the performance result.
Rerun your app using Xcode and, in the Mac OS toolbar for iOS Simulator, select Debug and then Color Blended Layers. Once we do that, we can see that our iOS Simulator shows a green overlay; this shows us how much memory iOS is using to process our rendered view, both native and non-native code, as shown here:
Currently, we can see a mostly green overlay with the exception of the status bar elements, which take up more render memory as they overlay the web view and have to be redrawn over that object repeatedly.
Let’s make a copy of our project and call it JS_Performance_CBL, and let’s update our index.html code with this code sample, as shown in the following screenshot:
Here, we have a simple page with an empty div; we also have a button with an onclick function called start. Our start function will update the height continuously using the setInterval function, increasing the height every millisecond. Our empty div also has a background gradient assigned to it with an inline style tag.
As expected, our div element that we’ve expanded now has a red overlay indicating that this is a confirmed performance issue, which is unavoidable. To correct this, we would need to remove the CSS gradient background, and it would show as green again. However, if we had to include a gradient in accordance with a design spec, a native version would be required.
When faced with UI issues such as these, it’s important to understand tools beyond normal developer tools and Web Inspectors, and take advantage of the mobile platform tools that provide better analysis of our code. Now, before we wrap this article, let’s take note of something specific for iOS web views.
The WKWebView framework
WKWebView does have limitations though; it can only be used for iOS8 or higher and it doesn’t have built-in Storyboard or XIB support like UIWebView. So, using this framework may be an issue if you’re new to iOS development. Storyboards are simply XML files coded in a specific way for iOS user interfaces to be rendered, while XIB files are the precursors to Storyboard. XIB files allow for only one view whereas Storyboards allow multiple views and can link between them too.
If you are working on an iOS app, I encourage you to reach out to your iOS developer lead and encourage the use of WKWebView in your projects.
For more information, check out Apple’s documentation of WKWebView at their developer site at https://developer.apple.com/library/IOs/documentation/WebKit/Reference/WKWebView_Ref/index.html.
Resources for Article:
- GUI Components in Qt 5 [article]