Is an Ionic Application Native?

I recently published a video that demonstrates why I think saying that Ionic applications are not native is inaccurate and confusing (even though it is perhaps the most common way to describe Ionic applications). I make the case for this by building a standard native application with Xcode/Swift and then adding Ionic to it:

This article is going to recap the same process of creating a native iOS application with Xcode and then getting an Ionic application running inside of it. I will also be expanding much more on my thoughts around this topic in this article. There are a few goals for this article:

  • To help give a sense of how Capacitor works behind the scenes
  • To demystify iOS/Swift and demonstrate how Ionic/Xcode/Swift work together
  • To teach a little bit of Swift syntax which can be utilised with Capacitor

But perhaps the key goal is to:

  • Demonstrate why I think referring to Ionic applications as “not native” is inaccurate and confusing terminology

To be clear, there is significant differences in the approach that Ionic takes and the approach a standard native application built entirely with Swift/Objective-C takes. There are also differences between the approach React Native takes and the approach a standard native application takes. Depending on the circumstance, this may have real implications that need to be considered and one approach may be far more suitable than the other. As such, we should distinguish between these different approaches with terminology that accurately defines these differences.

The point I will be making is that all of these approaches are native applications. They all result in native packages that can be submitted to the App Store. The differences between the approaches happen inside of the native applications, and that is the way that I think we should describe them.

1. Create a new Project in Xcode

Let’s quickly recap how to go about getting Ionic running inside of a native application by just building a standard native application.

IMPORTANT: You should absolutely not build Ionic applications this way. Capacitor already does this, and it does a much better job. What we are doing is pretty much creating a really basic version of Capacitor. The point of us doing this manually is so that we can explicitly see what is happening, rather than Capacitor doing it automatically behind the scenes.

  1. Open Xcode
  2. Go to File > New > Project
  3. Use the iOS Single View App template
Creating a new Xcode project

2. Add Webkit to the Projects Build Phases

  1. In the Projects configuration go to the Build Phases tab
  2. Expand Link Binary with Libraries
  3. Click the + button
  4. Search for Webkit
  5. Select WebKit.framework and then click Add
Adding WebKit to an Xcode project

3. Set up Webkit

  1. Add the following code to your ViewController.swift file:
import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

    private var webView: WKWebView?
    
    override public func loadView() {
        let webViewConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webViewConfiguration)
        webView?.scrollView.bounces = false
        webView?.uiDelegate = self
        webView?.navigationDelegate = self
        webView?.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs")
        view = webView
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }


}

This imports WebKit and configures a new WKWebView which we then assign to the view. We have used the same basic configuration options that Capacitor uses when created the web view (allowFileAccessFromFileURLs is important here as it will allow the index.html file that we load in the web view to load the other JavaScript and CSS files it depends on).

4. Add a Built Ionic Application to the Xcode Project

  1. Drag a built Ionic application (i.e. the www folder) into your Xcode application as shown below (you can just add it underneath Info.plist)
  2. Make sure that Copy items if needed is checked and that Added folders is set to Create folder references
Adding an Ionic application to an Xcode project

Although you would not typically do this in a standard Ionic/Capacitor application, you will also need to modify the index.html file inside of the www folder such that this line:

<base href="/" />

is changed to this:

<base href="./" />

If you do not do this, the JavaScript/CSS files will not load in correctly.

5. Load the Ionic code into the Web View

  1. Modify your ViewController.swift file to reflect the following:
import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

    private var webView: WKWebView?
    
    override public func loadView() {
        let webViewConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webViewConfiguration)
        webView?.scrollView.bounces = false
        webView?.uiDelegate = self
        webView?.navigationDelegate = self
        webView?.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs")
        view = webView
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let path = Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "www")
        let url = URL(fileURLWithPath: path!)
        let request = URLRequest(url: url)
        webView?.load(request)
        
    }


}

Now inside of the viewDidLoad hook we are creating a URL request for our index.html file inside of the www directory and then loading that into our web view. That’s it! We now have Ionic running inside of our native application:

An Ionic application running in a native Xcode project

Why is this Ionic application not native?

At what point in this process did the native application I created suddenly become not native? When I added the web view? When I loaded an Ionic application into that web view?

The application we have built has access to everything any standard native application does (because it is just a native application). It can access any native feature it wants, including using additional native controls on top of the web view. The only condition here is that if we want to make use of data retrieved natively inside of our user interface (e.g. a photo from the camera or data from storage) we would need to communicate that data to the web view so that the Ionic code can make use of it (this is something that Capacitor allows us to do).

The most noticeable difference here is that Ionic is primarily using the web view to display its user interface, whereas a standard native application uses the default native controls. It is common for people to draw the line here, and say that this is why Ionic is not native: because it doesn’t use the default native controls.

First, a WebKit View is one of the standard native user interface controls provided by iOS. But even if we exclude that, why would not making use of a specific subset of features that native applications offer suddenly make the application not native? When I first created the Xcode project, before I added the WebKit View, there were no native controls being used - was it not native at that point in time? We could drop other native controls on top of the Ionic application and make use of them (like modals, action sheets, alerts, and more), is there a certain number of native controls that need to be added? Why is usage of the user interface library the defining factor?

Some people will say that if it includes the WebKit View control it makes the application not native. This creates a very weird situation which where by adding a native control to your native application you make it less… “native”. But if we do take that definition, then many “typical” native applications wouldn’t be considered native, as many use web views to display at least parts of the user interface - I have not researched this myself to verify but I believe this includes big name applications like Instagram and Uber based on findings by others.

I realise I am being a bit silly here with my hypotheticals, and I don’t mean to come across as inflammatory. I just want to highlight the kinds of weird/confusing/absurd situations we have to discuss if we use “native” as the descriptor to distinguish between various approaches. Where do you draw the line?

What SHOULD we call these applications?

I don’t know. I’m just going to be the annoying person who points out issues without offering solutions. We do have the term “hybrid” for Ionic which is commonly used, which is better than simply labelling Ionic applications “not native”, but I still think it is a vague and confusing definition.

One commenter on my YouTube video said that it would be misleading to say to a client that Ionic is native. I agree that simply saying it is native is misleading, which gets to my point that the terminology as it is used today is inherently vague/confusing/misleading. It would be just as misleading to simply say that Ionic is not native.

If a client or a developer asks if Ionic is “native” the answer that would be useful and clarifying to them would depend on what exactly they mean. So saying Ionic is native and Ionic is not native here is misleading both ways.

  • If they want to know if the built output is the same as a standard native application, then the answer they are seeking would be: yes
  • If they want to know whether they can submit this to the app store, then the answer they are seeking would be: yes
  • If they want to know whether they can access native functionality like the camera or native file storage then the answer they are seeking would be: yes
  • If they wanted to know whether the user interface is implemented using native user interface controls then the answer would be (mostly): no

I can offer a few thoughts on how I would describe the nature of Ionic and alternatives, without using a blanket native/not-native term. This is how I would differentiate between the approaches I’ve mentioned in this article:

Applications built with Xcode/Swift/Objective-C, Ionic/Capacitor, and React Native are all native applications. Applications built with Xcode/Swift/Objective-C could be referred to as standard native applications. Applications built with Ionic/Capacitor could be referred to as native applications that primarily use Webkit/JavaScript to display the user interface and run business logic. Applications built with React Native could be referred to as native applications that use WebKit/JavaScript to run business logic and have their user interface interpreted into native controls at runtime.

Do these differences matter?

They might, but in a majority of cases the skills of the people building the applications are going to far outweigh any potential performance drawbacks of a particular approach.

There is this common perception that a “standard” native application will always outperform alternatives that have some level of abstraction going on inside (like Ionic and React Native). In theory this might be true, but the reality is very different. A standard native application might have more power available, but it is susceptible to the same coding/design flaws that any programming language is. I would take higher skilled developers building with Ionic over lesser skilled developers building standard native applications every day (even if we wipe out every other benefit of using Ionic like being able to share the exact same codebase over multiple platforms).

Try putting me in a V8 Supercar racing against Craig Lowndes in a stock standard Toyota Corolla. I don’t need to know much about cars to know that I am going to lose that race every time, despite the extra power I might have access to. If all we are interested in is city driving, then the Supercar gives me little to no benefit (and will likely be a hindrance).

What are your thoughts?

Although I’ve been a bit cheeky in this article, I do genuinely want to hear from, and have a discussion, with people who disagree with my view here. I think the majority of people do disagree with the view I have outlined.

Further resources

Check out my latest videos: