Cannot assign value of type 'MenuView' to type 'some View'

Viewed 2217

I noticed that you can only have a single .popover modifier in SwiftUI. I have to present two possible simple popovers, one of them a MenuView, the other a CreateChannelView.

For that I have:

@State private var popover: some View
@State private var showPopover = false

and then the modifier:

.popover(isPresented: self.$showPopover) {
    self.popover
}

The problem is that I don't see how can I assign instances of MenuView or CreateChannelView to popover as I get the error:

Cannot assign value of type 'MenuView' to type 'some View'

This is a little bit different than this question which passes generic views in the init method.

2 Answers

The solution was to use AnyView:

@State private var popover: AnyView

Then it can be assigned as:

self.popover = AnyView(CreateChannelView(showing: self.$showPopover))

You can declare the two views as two different variables and then toggle selection between them with a boolean that determines which is presented. I made an example program with the information you gave me:

struct ContentView: View {
    let buttonSize: CGFloat = 30
    @State var isPresented = false
    @State var usePopover1 = true
    var popover1: some View {
        Text("Popover 1")
    }
    var popover2: some View {
        Image(systemName: "star")
    }
    var body: some View {
        VStack {
            Button(action: {
                self.isPresented = true
            }) {
                Text("Present popover")
            }
            Button(action: {
                self.usePopover1.toggle()
            }) {
                Text("Switch from \(self.usePopover1 ? "popover1" : "popover2") to \(self.usePopover1 ? "popover2" : "popover1")")
            }
        }.popover(isPresented: $isPresented) {
            if self.usePopover1 {
                AnyView(self.popover1)
            } else {
                AnyView(self.popover2)
            }
        }
    }
}

I just made the two popovers on the spot for demonstration purposes, but you can declare yours as being the two different types you mentioned in your question (let popover1: MenuView = MenuView(...) and let popover2: CreateChannelView = CreateChannelView(...)).

Related