Implementing AR in SwiftUI… without Storyboards

Madison Gipson
Jun 13, 2020 · 4 min read
Photo by freestocks on Unsplash

AR is usually implemented with Storyboards, but it doesn’t have to be. This tutorial is for my fellow devs who want to pair SwiftUI with AR, without the hassle of Storyboards.

Let’s Start

Go to your existing SwiftUI project; for this demo, I created a new Single View SwiftUI project.

Create a Single View App.
Choose SwiftUI for User Interface.

Good news! For this integration, there’s no messing with AppDelegate.swift or SceneDelegate.swift required. The only files we’ll be looking at are ContentView.swift and ARView.swift (which you’ll create next).

Add the AR View

Create your ARView.swift file as a regular Swift file.

Create ARView.swift as a regular swift file.
Overview of all files in project.

ARView.swift is a blank slate. We need to import ARKit and declare the ARView class with UIViewController and ARSCNViewDelegate protocols.

import Foundation
import ARKit
class ARView: UIViewController, ARSCNViewDelegate {}

Now we need to actually create an ARView. This is usually where an AR project using storyboards has an IBAction outlet.

Instead of using this, we’ll add the following code (bolded):

import Foundation
import ARKit
class ARView: UIViewController, ARSCNViewDelegate { var arView: ARSCNView {
return self.view as! ARSCNView
}
override func loadView() {
self.view = ARSCNView(frame: .zero)
}
}

Now let’s load, assign a delegate, and create a scene for this new arView.

import Foundation
import ARKit
class ARView: UIViewController, ARSCNViewDelegate {

var arView: ARSCNView {
return self.view as! ARSCNView
}
override func loadView() {
self.view = ARSCNView(frame: .zero)
}
override func viewDidLoad() {
super.viewDidLoad()
arView.delegate = self
arView.scene = SCNScene()
}
}

Next, we’ll add the final bits to our ARView class; these are standard AR view and session handling functions.

import Foundation
import ARKit
class ARView: UIViewController, ARSCNViewDelegate {

var arView: ARSCNView {
return self.view as! ARSCNView
}
override func loadView() {
self.view = ARSCNView(frame: .zero)
}
override func viewDidLoad() {
super.viewDidLoad()
arView.delegate = self
arView.scene = SCNScene()
}
// MARK: - Functions for standard AR view handling
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let configuration = ARWorldTrackingConfiguration()
arView.session.run(configuration)
arView.delegate = self
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
arView.session.pause()
}
// MARK: - ARSCNViewDelegate
func sessionWasInterrupted(_ session: ARSession) {}

func sessionInterruptionEnded(_ session: ARSession) {}
func session(_ session: ARSession, didFailWithError error: Error)
{}
func session(_ session: ARSession, cameraDidChangeTrackingState
camera: ARCamera) {}
}

At this point, make sure to add camera access to the Info.plist, otherwise your AR view won’t be allowed to present and cause a nasty SIGABRT error.

Allow camera access.

Tie it Together

To transition between this ARView and SwiftUI, we need to add some ViewIndicators to ARView.swift and Content.swift.

Starting with ARView.swift, add the following above the ARView class declaration.

... //other imports
import SwiftUI
// MARK: - ARViewIndicator
struct ARViewIndicator: UIViewControllerRepresentable {
typealias UIViewControllerType = ARView

func makeUIViewController(context: Context) -> ARView {
return ARView()
}
func updateUIViewController(_ uiViewController:
ARViewIndicator.UIViewControllerType, context:
UIViewControllerRepresentableContext<ARViewIndicator>) { }
}
... //ARView class declaration and rest of code

Switching over to ContentView.swift, you’ll want to add a similar ViewIndicator but with a different name.

// MARK: - NavigationIndicatorstruct NavigationIndicator: UIViewControllerRepresentable {
typealias UIViewControllerType = ARView
func makeUIViewController(context: Context) -> ARView {
return ARView()
}
func updateUIViewController(_ uiViewController:
NavigationIndicator.UIViewControllerType, context:
UIViewControllerRepresentableContext<NavigationIndicator>) { }
}
... //ContentView Struct

Final Touches

So we have a Storyboard-free ARView class and ViewIndicators in ARView.swift and ContentView.swift that seamlessly transition between the two views.

We still need a way to get to the ARView from the ContentView home screen though. Let’s add a stack structure and a couple buttons to ContentView.swift to prompt the ARView; this method of calling the views will be the same even in a more complex context.

... //NavigationIndicatorstruct ContentView: View {
@State var page = "Home"

var body: some View {
VStack {
if page == "Home" {
Button("Switch to ARView") {
self.page = "ARView"
}
} else if page == "ARView" {
ZStack {
NavigationIndicator()
VStack {
Spacer()
Spacer()
Button("Home") {
self.page = "Home"
}.padding()
.background(RoundedRectangle(cornerRadius: 10)
.foregroundColor(Color.white).opacity(0.7))
}
}
}
}
}
}

Running the project should show something like this:

Check out the full code on Github.

Enjoy! Follow for more articles & tutorials on iOS dev, anything Swift, and general programming!

Dev Genius

Coding, Tutorials, News, UX, UI and much more related to development

Sign up for Best Stories

By Dev Genius

The best stories sent monthly to your email. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Dev Genius

Coding, Tutorials, News, UX, UI and much more related to development

Madison Gipson

Written by

Student & intern learning how to make the world a better place with code.

Dev Genius

Coding, Tutorials, News, UX, UI and much more related to development

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

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