Logo for tanaschita.com

How to implement a UIViewController delegate when working with SwiftUI

Learn how to use SwiftUI's coordinators to communicate with UIKit.

08 May 2023 · 4 min read

When building iOS applications, we sometimes need to use UIKit's UIViewController in a SwiftUI view, for example due to an older code base. When doing so, we may need to pass data from the view controller to the SwiftUI view. For that, SwiftUI provides so called coordinators.

Let's look at an example to understand how they work.

Sponsorship logo
Preparing for a technical iOS job interview - updated for iOS 17
Check out my book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift, SwiftUI, Combine, HTTP Networking, Authentication, SwiftData & Core Data, Concurrency with async/await, Security, Automated Testing, Machine Learning and more.
LEARN MORE

Let's say, we'd like to use the native DataScannerViewController to implement a data scanner in a SwiftUI application.

To be more precise, what we'd like to achieve is to open the DataScannerViewController from a SwiftUI view and after the user has finished scanning a QR code, to get that scanned data communicated back to our SwiftUI view.

As a first step, let's look at how to show the scanner view controller from a SwiftUI view. For that, SwiftUI provides the UIViewControllerRepresentable protocol:

struct ScannerView: UIViewControllerRepresentable {
@Binding var code: String?
func makeUIViewController(context: Context) -> DataScannerViewController {
let viewController = DataScannerViewController(
recognizedDataTypes: [.barcode(symbologies: [.qr])])
return viewController
}
func updateUIViewController(_ uiViewController: DataScannerViewController, context: Context) {
}
}

With the code above, we are now able to use the ScannerView in SwiftUI, for example:

struct ContentView: View {
@State private var code: String?
@State private var showingScanner = false
var body: some View {
VStack {
Text(code ?? "")
Button("Scan QR code") {
showingScanner = true
}
}
.sheet(isPresented: $showingScanner) {
ScannerView(code: $code)
}
}
}

So far, the code binding we pass into the scanner view never gets updated by it. To be able to do that, we need to setup the scanner view controller's delegate at first. Only reference types can conform to DataScannerViewControllerDelegate, so we can't use the ScannerView itself since it's a struct which is not a reference type.

For those cases, SwiftUI provides a built in solution. Any UIViewControllerRepresentable type can declare a nested Coordinator reference type and implement the makeCoordinator() method:

struct ScannerView: UIViewControllerRepresentable {
class Coordinator {
@Binding var code: String?
init(code: Binding<String?>) {
_code = code
}
}
func makeCoordinator() -> Coordinator {
Coordinator(code: $code)
}
...
}

We can then extend the coordinator to serve as DataScannerViewControllerDelegate:

class Coordinator: DataScannerViewControllerDelegate {
@Binding var code: String?
init(code: Binding<String?>) {
_code = code
}
func dataScanner(_ dataScanner: DataScannerViewController, didAdd addedItems: [RecognizedItem], allItems: [RecognizedItem]) {
guard let item = allItems.first else { return }
switch item {
case .barcode(let recognizedCode):
print(recognizedCode.payloadStringValue)
code = recognizedCode.payloadStringValue
default:
break
}
}
}

SwiftUI will automatically call this method and associate the returned object with the context that is passed into the makeUIViewController method. There, we can use it to set the scanner view controller delegate:

func makeUIViewController(context: Context) -> DataScannerViewController {
let viewController = DataScannerViewController(
recognizedDataTypes: [.barcode(symbologies: [.qr])])
viewController.delegate = context.coordinator
return viewController
}
Sponsorship logo
Preparing for a technical iOS job interview - updated for iOS 17
Check out my book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift, SwiftUI, Combine, HTTP Networking, Authentication, SwiftData & Core Data, Concurrency with async/await, Security, Automated Testing, Machine Learning and more.
LEARN MORE

Newsletter

Image of a reading marmot
Subscribe

Like to support my work?

Say hi

Related tags

Articles with related topics

swiftui

uikit

swift

ios

SF Symbols guide for SwiftUI and UIKit

Learn how to use symbol images provided by Apple in iOS applications.

31 Jan 2022 · 5 min read

Latest articles and tips

© 2024 tanaschita.com

Privacy policy

Impressum