简体   繁体   中英

SwiftUI List with different cells per section

I'm trying to create a List of questions.

I was planning to create a 'section' per question and have each row change upon the type

Now I have a lot of different types of questions.

Let's say for example:

  1. Ask some text input
  2. Select from a picker
  3. Multiple select (so simply show all options)

I have this kind of setup working in 'regular' iOS However, when trying to implement such a thing in SwiftUI, the preview keeps freeing, I can't seem to get the build working either. I don't really get any feedback from xcode.

Example code:

import SwiftUI

struct Question: Hashable, Codable, Identifiable {
    
    var id: Int
    var label: String
    var type: Int
    var options: [Option]?
    var date: Date? = nil
}

struct Option : Hashable, Codable, Identifiable {
    var id: Int
    var value: String
}

struct MyList: View {
    
    
    var questions: [Question] = [
        Question(id: 1, label: "My first question", type: 0),
        Question(id: 2, label: "My other question", type: 1, options: [Option(id: 15, value: "Yes"), Option(id: 22, value: "No")]),
        Question(id: 3, label: "My last question", type: 2, options: [Option(id: 4, value: "Red"), Option(id: 5, value: "Green"), Option(id: 6, value: "Blue")])
    ]
    
    var body: some View {
        List {
            ForEach(questions) { question in
                Section(header: Text(question.label)) {

                    if(question.type == 0)
                    {
                        Text("type 0")
                        //Show text entry row
                    }
                    else if(question.type == 1)
                    {
                        Text("type 1")
                        //Show a picker containing all options
                    }
                    else
                    {
                        Text("type 2")
                        //Show rows for multiple select

//
//                    IF YOU UNCOMMENT THIS, IT STARTS FREEZING
//
//                        if let options = question.options {
//                            ForEach(options) { option in
//                                Text(option.value)
//                            }
//                        }
                    }
                    
                }
            }
        }
    }
}

struct MyList_Previews: PreviewProvider {
    static var previews: some View {
        MyList()
    }
}

Is such a thing possible in SwiftUI ? What am I missing ? Why is it freezing ?

Your code is confusing the Type checker. If you let it build long enough Xcode will give you an error stating that the type checker could not be run in a reasonable amount of time. I would report this as a bug to Apple, perhaps they can improve the type checker. In the mean time you can get your code to work by simplifying the expression that the ViewBuiler is trying to work through. I did it like this:

import SwiftUI

struct Question: Hashable, Codable, Identifiable {
    var id: Int
    var label: String
    var type: Int
    var options: [Option]?
    var date: Date? = nil
}

struct Option : Hashable, Codable, Identifiable {
    var id: Int
    var value: String
}

struct Type0View : View {
    let question : Question

    var body : some View {
        Text("type 0")
    }
}

struct Type1View : View {
    let question : Question

    var body : some View {
        Text("type 1")
    }
}

struct Type2View : View {
    let question : Question

    var body : some View {
        Text("type 1")

        if let options = question.options {
            ForEach(options) { option in
                Text(option.value)
            }
        }
    }
}

struct ContentView: View {
    var questions: [Question] = [
        Question(id: 1, label: "My first question", type: 0),
        Question(id: 2, label: "My other question", type: 1, options: [Option(id: 15, value: "Yes"), Option(id: 22, value: "No")]),
        Question(id: 3, label: "My last question", type: 2, options: [Option(id: 4, value: "Red"), Option(id: 5, value: "Green"), Option(id: 6, value: "Blue")])
    ]

    var body: some View {
        List {
            ForEach(questions) { question in
                Section(header: Text(question.label)) {


                    if(question.type == 0)
                    {
                        Type0View(question: question)
                    }
                    else if(question.type == 1)
                    {
                        Type1View(question: question)
                    }
                    else
                    {
                        Type2View(question: question)
                    }

                }
            }
        }
    }
}

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

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