Adding SwiftUI to Objective-C Apps

Field Notes on freshening up legacy iOS apps

Our Boat Watch app is pretty successful, but as busy developers we’ve got out of step with Storyboards, autolayout, and other (not so recent) additions to iOS UI development workflow — they offer benefits, of course, but were too much of an overhead to retrofit into a working app , and as a result we’ve largely let these pass by. SwiftUI, announced at the 2019 Apple Devcon, has piqued our interest though — it looks like a significant step change in UI development, and I feel that using it would enable us to freshen our apps, and hopefully enable them to more readily adapt to new device sizes and UI metaphors. The big question, of course, is how to add SwiftUI views into a legacy Objective-C app, especially when - due disclaimer - I’ve never written a line of Swift in my life!

As it turns out, its pretty simple — at least to get to the simple integration that I’m at now. It took quite a bit of piecing together, so I’ll share some notes here in case it helps others…

Step 1. Add a SwiftUI file to the project
In Xcode, choose File → New File and select a SwiftUI file. Xcode will offer to create a bridging header, I just said “OK” to that. This will add a very simple SwiftUI view to the project... using the name you gave to the file for the view. I’ve extended the template code a little to add a variable that will be passed from my Objective-C code and onto the UI…

// BoatDetailsView.swift
import SwiftUIstruct BoatDetailsView : View {
var shipName = ""
var body: some View {

Step 2. Add a mediating Swift file to the project
(It’s possible that this step isn’t needed, but this technique worked for me)

I think of this file as a bridge between the Objective-C code of my app and the new Swift UI interface code — its job is simply to instantiate the SwiftUI view and return a pointer to the UIViewController to the calling Obj-C code - the “objc” tags allow the class and functions to be called from Obj-C… the variable that is displayed on the UI is passed through this bridging code — one thing to observe in the code below — the makeShipDetailsUI function has a first parameter which is called “_” — the reason for this is to make it possible to call the function from Objective-C without specifying the first parameter name (see the next code block where the function is called from ObjC— hopefully this will make sense then…)

// BoatDetailsInterface.swift
import Foundation
import SwiftUI
class BoatDetailsInterface: NSObject {

@objc func makeShipDetailsUI(_ name: String) -> UIViewController{
var details = BoatDetailsView()
details.shipName = name
return UIHostingController(rootView: details)

Step 3. Call the mediating Swift function from the Objective-C code
There’s a little bit of house-keeping to do in the Objective-C .m file first — you need to add an import of a header file — you don’t need to make the header file, just give it the right name, which is the name of your module (with underscores for any spaces in the name) — this step, and other housekeeping for Objective-C and Swift integration is well documented elsewhere — this iOS Dev Diary from Jay Versluis was a great help.

#import "Boat_Watch-Swift.h"

And then finally you can call up the new SwiftUI view from your Objective-C, in a button handler, for example… — note the variable being passed into the Swift function.

UIViewController *detailsViewController = [[BoatDetailsInterface new] makeShipDetailsUI:@"Sarita"];[self presentModalViewController:detailsViewController animated:YES];

And here it is — obviously this is just a really simple demo, but you can see the text passed from the Objective-C is displayed in the SwiftUI view.

As regards a more complete UI here, there are plenty of SwiftUI tutorials emerging and I’ve made a promising start fleshing this form out — I would imagine there will be more state to share from the Objective-C code into the Swift code — and back again, which I’ve yet to explore…

Hope this helps — please clap the post if you find it useful…



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store