简体   繁体   中英

Dynamic view rendering, SwiftUI

Let's say I have a struct:

var topMenu: [TopMenu] = [TopMenu(name: "Menu", index: 1),
                      TopMenu(name: "Search", index: 2),
                      TopMenu(name: "Profile", index: 3),
                      TopMenu(name: "Settings", index: 4)]

This struct contains a string and an index, so I can create a menu based on a HStack and a ForEach with this elements. This is fine. But what I'm trying to do now is the following:

Let's say this struct is dynamic: I can have 3 elements but I can also have 5/6 elements (based on a backend call). And I would like to render a different view for each of this element (on click). At the moment i'm doing this with a simple if based on our index:

if self.index == 1 {
      First()
} else if self.index == 2 {
      Second()
} else if self.index == 3 {
      Third()
} else {
      First()
}

But this is not the best approach if I have more elements etc ...

My thought are the following, but I don't know what is the best approach for this:

  • Create a funcion that returns Any View based on the index and give for each view a default name so I can iterate on? For example View1, View2 etc?

  • Add something particular to my struct?

Ps I would also like to do this in the safer way possible, I don't want crash etc! =)

Thank you!

Here is possible approach in SwiftUI 2.0 (in SwiftUI 1.0 ViewBuilder does not support yet switch , so if/else is the only way, but you can wrap it in enum as well).

enum Choices: Int {
    case menu = 1
    case search = 2
    case profile = 3
    case settings = 4

    @ViewBuilder
    func view() -> some View {
        switch self {
            case menu:
                MenuView()
            case search:
                SearchView()
            case profile:
                ProfileView()
            case settings:
                SettingsView()
        }
    }
}

struct DemoChoicesUsage: View {
    @State var index = 1
    var body: some View {
        VStack {
            (Choices(rawValue: index) ?? Choices.menu).view()
        }
    }
}

Also, optionally, you can modify also TopMenu to be linked directly to enum cases instead of indexes, like TopMenu(name: "Menu", tag: .menu)

struct TopMenu {
  let name: String
  let tag: Choices
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM