I can do a static List like
List { View1() View2() }
But how do i make a dynamic list of elements from an array? I tried the following but got error: Closure containing control flow statement cannot be used with function builder 'ViewBuilder'
let elements: [Any] = [View1.self, View2.self] List { ForEach(0..<elements.count) { index in if let _ = elements[index] as? View1 { View1() } else { View2() } } }
Is there any work around for this? What I am trying to accomplish is a List contaning dynamic set of elements that are not statically entered.
Probably the simplest way to build a list is to create a new SwiftUI view and wrap the Hello World text in a List: struct StaticListView: View { var body: some View { List { Text("Hello, world!") } } } To add more items to the list, we can just add another line: List { Text("Hello, world!") Text("Hello, SwiftUI!") }
If you have configured a SwiftUI list view to support deletion or editing of its items, you can allow the user to toggle editing mode for your list view by adding an EditButton somewhere. When that is run, you'll find you can tap the edit button to enable or disable editing mode for the items in the list.
SwiftUI gives us equivalents to UIKit's viewDidAppear() and viewDidDisappear() in the form of onAppear() and onDisappear() . You can attach any code to these two events that you want, and SwiftUI will execute them when they occur.
Looks like the answer was related to wrapping my view inside of AnyView
struct ContentView : View { var myTypes: [Any] = [View1.self, View2.self] var body: some View { List { ForEach(0..<myTypes.count) { index in self.buildView(types: self.myTypes, index: index) } } } func buildView(types: [Any], index: Int) -> AnyView { switch types[index].self { case is View1.Type: return AnyView( View1() ) case is View2.Type: return AnyView( View2() ) default: return AnyView(EmptyView()) } } }
With this, i can now get view-data from a server and compose them. Also, they are only instanced when needed.
if/let
flow control statement cannot be used in a @ViewBuilder
block.
Flow control statements inside those special blocks are translated to structs.
e.g.
if (someBool) { View1() } else { View2() }
is translated to a ConditionalValue<View1, View2>
.
Not all flow control statements are available inside those blocks, i.e. switch
, but this may change in the future.
More about this in the function builder evolution proposal.
In your specific example you can rewrite the code as follows:
struct ContentView : View { let elements: [Any] = [View1.self, View2.self] var body: some View { List { ForEach(0..<elements.count) { index in if self.elements[index] is View1 { View1() } else { View2() } } } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With