Skip to Content
Technical Articles

UI5 and SwiftUI

Ok, it feels a bit odd to write a Swift blog in SAP Community but let’s give it a try. 🙂

In 2019 Apple released its new UI Framework SwiftUI beside UIKit and I was wondering if this new framework could be also used to display an UI5 App.

This solution will show how easy it is to build an own native browser with SwiftUI starting a UI5 application.

I’m aware that there a several very good opportunities to achieve the same using SAP HAT,  SAP iOS SDK or Apache Cordova but for the sake of curiosity…

Let’s dive into it.

To follow along you’ll need an apple device with the latest Xcode IDE installed. Furthermore please download the sample UI5 application from here and finally download the latest UI5 framework from here.

Once downloaded the app and the runtime we go ahead, start Xcode and create a new project.

Choose Single View App

On the next screen we give our app a name and make sure SwiftUI is selected as User Interface. We save the project on our local machine.

Xcode will provide a simple Hello World sample application. We will adapt and enhance it step by step.

To run the UI5 sample app which we have downloaded previously on our Apple device we will make use of WKWebView which is part of the WebKit package. WebKitView will help us to display web content. It acts like a mini in app browser. So right after the import SwiftUI command import WebKit as well:

import WebKit

 

WebKitView is a subclass from UIKit. To use UIKit subclasses in SwiftUI we can create a custom wrapper.

We will create a wrapper for WebKitView by creating a new struct that conforms to the UIViewRepresentable protocol.

Our code should look like this. We place it right after the package imports and before your content view.

struct WebView : UIViewRepresentable { 
    let request: URLRequest  
    func makeUIView(context: Context) -> WKWebView  {  

        return WKWebView()  
    }  
    func updateUIView(_ uiView: WKWebView, context: Context) {  
        uiView.load(request)  
    }  
}  

Our new struct has one property which stores the URL and two methods. makeUIView() creates and returns the WKWebView object and updateUIView will use this object to load a web page.

We replace the “Hello World” View with our new created view object and create a constant with a valid URL to test our application. The content view should look like this:

struct ContentView: View {
    let url = URL(string: "https://www.sap.com")!
    var body: some View {
        WebView(request: URLRequest(url: url))
    }
}

Now we build and run the application by pressing command + r. We can now see the web page.

Next we are going to copy the sample UI5 app and the UI5 framework into our project. You can just drag and drop the webapp folder into the Xcode project explorer. Make sure the option “Copy items if needed” is marked. Rename the resources folder of the UI5 framework to i.e. res and drag and drop it into the webapp folder.

Xcode won’t compile your project unless you have renamed the resources folder.

Furthermore we have to make sure that the app files will be found during build phase of our project. To do this we have to select our project in Xcode on the left and choose Build Phases. In section Copy Bunlde Ressources we can add all files from webapp folder.

Once we have our files in place we can now change our code to start the application. This can be achieved by using method loadHTMLString of our WKWebView object. We create a new property and delete the existing property request in our struct WebView because we don’t need it any more:

    //let request: URLRequest
    let strUrl: URL

Xcode will throw an error. We are going to fix this soon.

Next we have to allow access to local files. This can be done in method makeUIView. We replace the existing code like this.

    func makeUIView(context: Context) -> WKWebView  {
        let webView = WKWebView()
        webView.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs")
        return webView
        
    }

In method updateUIView we change the method call from load to loadHTMLString:

    func updateUIView(_ uiView: WKWebView, context: Context) {
        do {
            uiView.loadHTMLString( try String(contentsOf: strUrl, encoding: .utf8), baseURL: Bundle.main.resourceURL)
        } catch  {
            print("Unable to get the file.")
        }
    }

Now we need to start our application from index.html file which we load from the project.

Place a new constant in our content view:

let htmlPathURL = Bundle.main.url(forResource: "index", withExtension: "html")!

Finally we fix WebView creation according to the newly created property and the Xcode compiler should be happy again.

struct ContentView: View {
    let htmlPathURL = Bundle.main.url(forResource: "index", withExtension: "html")!
    var body: some View {
        WebView(strUrl: htmlPathURL)
    }
}

The very last thing that has to be adapted is the index.html. We have to make sure that the UI5 sources can be found locally (change src property like this):

	<script id="sap-ui-bootstrap"
		src="./res/sap-ui-core.js"
		data-sap-ui-theme="sap_fiori_3"
		data-sap-ui-libs="sap.m, sap.ui.layout, sap.tnt"
		data-sap-ui-resourceroots='{"Quickstart": "./"}'
		data-sap-ui-onInit="module:Quickstart/index"
		data-sap-ui-compatVersion="edge"
		data-sap-ui-async="true">
	</script>

Build and run your app:

As a result you can see the UI5 App running on your iOS Device.

Full source code of contentView.swift can be found here.

Of course the are much more things you can do and other things that can be considered. If you would like to learn more about WKWebView check out this blog.

Also check out my project on github or in the Apple AppStore.

Happy coding!

Be the first to leave a comment
You must be Logged on to comment or reply to a post.