Bart van Kuik
Bart van Kuik

Reputation: 4852

Error: enum case requires that closure conforms to 'View'

I wish to create a UIViewRepresentable with SwiftUI views as a subview, and I have the following code, which can be pasted over the ContentView of an empty SwiftUI project in Xcode.

The enum Action right now has a single case, but is a hook to add additional actions that will be executed in updateUIView().

import SwiftUI

struct LegacyView<Content: View>: UIViewRepresentable {
    enum Action {
        case idle
    }

    @Binding var action: Action
    let content: Content

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> UIView {
        let hosting = UIHostingController(rootView: self.content)
        let legacyView = UIView()
        legacyView.addSubview(hosting.view)
        hosting.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        return legacyView
    }

    func updateUIView(_ uiView: UIView, context: Context) {
    }

    class Coordinator: NSObject {
        let parent: LegacyView

        init(_ parent: LegacyView) {
            self.parent = parent
        }
    }
}

struct ContentView: View {
    var body: some View {
        LegacyView(action: .constant(.idle)) {
            Text("Hello, world!")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

However at the first line in the body of the ContentView, I get the following error: Enum case 'idle' requires that '() -> Text' conform to 'View'. How can this error be fixed?

Upvotes: 1

Views: 140

Answers (1)

Asperi
Asperi

Reputation: 257563

Here is corrected code for LegacyView according to intended usage in ContentView...

struct LegacyView<Content: View>: UIViewRepresentable {
    enum Action {
        case idle
    }

    @Binding var action: Action
    let content: () -> Content // << builder type

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> UIView {
        let hosting = UIHostingController(rootView: self.content()) // << used builder
        let legacyView = UIView()
        legacyView.addSubview(hosting.view)
        hosting.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        return legacyView
    }

    func updateUIView(_ uiView: UIView, context: Context) {
    }

    class Coordinator: NSObject {
        let parent: LegacyView

        init(_ parent: LegacyView) {
            self.parent = parent
        }
    }
}

Upvotes: 2

Related Questions