How can I display a random view?

I want to display a random view, whether it's the firstScreen, secondSscreen or thirdScreen as seen in the pictures. I tried selecting a random element from my array but that does not seem to work. I hope you can help me! Thank you!

Answered by darkpaw in 737131022

It's because Swift doesn't know what type the value in screens is.

If you used this:

@State var screens: Array<FirstScreen> = [FirstScreen(), FirstScreen(), FirstScreen()]

Swift would know that screens is an array of FirstScreen, and so it can supply that view to ContentView. However, that's clearly not very useful, so you need to wrap it in AnyView.

Here you go:

struct ContentView : View {
	@State var screens: [Any] = [FirstScreen.self, SecondScreen.self, ThirdScreen.self]

	var body: some View {
		self.buildView(types: self.screens, index: Int.random(in: 0..<screens.count))
	}

	func buildView(types: [Any], index: Int) -> AnyView {
		switch types[index].self {
			case is FirstScreen.Type: return AnyView(FirstScreen())
			case is SecondScreen.Type: return AnyView(SecondScreen())
			case is ThirdScreen.Type: return AnyView(ThirdScreen())
			default: return AnyView(FirstScreen())
		}
	}
}
Accepted Answer

It's because Swift doesn't know what type the value in screens is.

If you used this:

@State var screens: Array<FirstScreen> = [FirstScreen(), FirstScreen(), FirstScreen()]

Swift would know that screens is an array of FirstScreen, and so it can supply that view to ContentView. However, that's clearly not very useful, so you need to wrap it in AnyView.

Here you go:

struct ContentView : View {
	@State var screens: [Any] = [FirstScreen.self, SecondScreen.self, ThirdScreen.self]

	var body: some View {
		self.buildView(types: self.screens, index: Int.random(in: 0..<screens.count))
	}

	func buildView(types: [Any], index: Int) -> AnyView {
		switch types[index].self {
			case is FirstScreen.Type: return AnyView(FirstScreen())
			case is SecondScreen.Type: return AnyView(SecondScreen())
			case is ThirdScreen.Type: return AnyView(ThirdScreen())
			default: return AnyView(FirstScreen())
		}
	}
}

Use ViewBuilder to get the random view.

I created 5 views to better see the randomness.

struct TheFirstView: View {
    var body: some View {
        Text("First view")
    }
}

struct TheSecondView: View {
    var body: some View {
        Text("Second view")
    }
}

struct TheThirdView: View {
    var body: some View {
        Text("Third view")
    }
}

struct TheFourthView: View {
    var body: some View {
        Text("Fourth view")
    }
}

struct TheFifthView: View {
    var body: some View {
        Text("Fifth view")
    }
}

@ViewBuilder func aleatView() -> some View {
    let alea = [1, 2, 3, 4, 5].randomElement() ?? 0
    switch alea {
        case 1: TheFirstView()
        case 2: TheSecondView()
        case 3: TheThirdView()
        case 4: TheFourthView()
        case 5: TheFifthView()
        default: EmptyView()
    }
}

struct ContentView90: View {
    @State private var redraw = true

    var body: some View {
        aleatView()
        Text("")
        Button(action: {
            redraw.toggle()
        }) {
            if redraw {  // Needed to detect state var has changed
                Image(systemName: "moon.fill")
            } else {
                Image(systemName: "moon")
            }
            Text("Shuffle")
        }
    }
}
How can I display a random view?
 
 
Q