简体   繁体   中英

Creating a dynamic List with section headers in SwiftUI?

I'm experimenting with SwiftUI and I'm trying to build a workout tracker app that I've already sketched in UIKit. I am trying to build an exercise list for the user to consult, so when the app starts I load some exercises in CoreData, and the Exercise has the following properties.

@NSManaged public var name: String
@NSManaged public var muscleGroup: String
@NSManaged public var exerciseDescription: String
@NSManaged public var type: String
@NSManaged public var id: UUID

When I'm building the list view, I retrieve an array of Exercise from CoreData and load them in a list. This work fine with a basic list, the thing is I would like to create a List with section headers in alphabetical order. In UIKit I did this by building a dictionary of the form [ "Prefix" : [Exercise]], and using the keys as section headers. This is practical because I could give the user sorting option just by changing the dictionary and reloading the data. In SwiftUI, I can't seem to make it work because I can't work on the fetch request object before view creation, and I can't iterate over dictionaries. Here is my code:

import SwiftUI
import CoreData

struct ExerciseListUIView: View {

@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(
    entity: Exercise.entity(),
    sortDescriptors: [
        NSSortDescriptor(keyPath: \Exercise.name, ascending: true)
    ]
) var exerciseList: FetchedResults<Exercise>

@State private var prefixList = [String]()

var body: some View {

    return NavigationView {

        VStack{
            List(exerciseList, id: \.self) { exercise in
                Text(exercise.name)
            }
        }
        .navigationBarTitle("Exercises")
    }
}
}

I tried a bunch of things but nothing seem to work. The most promising solution seems to store exercises directly in a different data structure, ExercisesByLetter(prefix: "String", exercises: [Exercise]), retrieve an array of [ExercisesByLetter] and iterate on that for building the list, but that would mean changing the way I store data, adding more work in the data storage functions and being forced to add different storages for each sorting option, like ExercisesByMuscleGroup, ExercisesByEquipment, and so on.

Let me know what you think, Thanks.

For anyone interested in the solution, I came up with the following. I created a ViewModel for my main View to manipulate the data. In that view model I retrieve all the Exercise as an array of [Exercise] from CoreData, and store them in a property of the ViewModel. I created then an helper function to iterate through the list of [Exercise] and create an array of [ExercisesBy]. This type contains a property which stores the sorting criterion (first letter, muscle group, equipment, etc) and another property which stores the array of Exercise which adhere to that criterion.

This array of ExercisesBy is then iterated from my view to construct the sectioned list.

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