Implement delegates within SwiftUI Views

You need to create a view that conforms to UIViewControllerRepresentable and has a Coordinator that handles all of the delegate functionality.

For example, with your example view controller and delegates:

struct SomeDelegateObserver: UIViewControllerRepresentable {
    let vc = SomeViewController()
    var foo: (Data) -> Void
    func makeUIViewController(context: Context) -> SomeViewController {
        return vc
    }

    func updateUIViewController(_ uiViewController: SomeViewController, context: Context) { }
    func makeCoordinator() -> Coordinator {
        Coordinator(vc: vc, foo: foo)
    }

    class Coordinator: NSObject, SomeDelegate {
        var foo: (Data) -> Void
        init(vc: SomeViewController, foo: @escaping (Data) -> Void) {
            self.foo = foo
            super.init()
            vc.delegate = self
        }
        func someDelegateFunction(data: Data) {
            foo(data)
        }
    }
}

Usage:

struct ContentView: View {
    var dataModel: DataModel

    var body: some View {
        NavigationLink(destination: CustomView(numberFromPreviousView: 10)) {
            Text("Go to VCRepresentable")
        }
    }
}

struct CustomView: View {
    @State var instanceData1: String = ""
    @State var instanceData2: Data?
    var numberFromPreviousView: Int // example of data passed from the previous view to this view, the one that can react to the delegate's functions
    var body: some View {
        ZStack {
            SomeDelegateObserver { data in
                print("Some delegate function was executed.")
                self.instanceData1 = "Executed!"
                self.instanceData2 = data
            }
            VStack {
                Text("This is the UI")
                Text("That, in UIKit, you would have in the UIViewController")
                Text("That conforms to whatever delegate")
                Text("SomeDelegateObserver is observing.")
                Spacer()
                Text(instanceData1)
            }
        }
    }
}

Note: I renamed VCRepresentable to SomeDelegateObserver to be more indicative of what it does: Its sole purpose is to wait for delegate functions to execute and then run the closures (i.e foo in this example) you provide it. You can use this pattern to create as many functions as you need to “observe” whatever delegate functions you care about, and then execute code that can update the UI, your data model, etc. In my example, when SomeDelegate fires someDelegateFunction(data:), the view will display “Excuted” and update the data instance variable.

Leave a Comment