luegm.dev
luegm.dev

Reputation: 161

SwiftUI SortDescriptor @State

I want to change the sortDescriptor with a button.
But if I change the variables "sorting" and "sortOrder" to @State variables I get an Error.

The error-message is: Variable 'self.fetchRequest' used before being initialized

@Environment(\.managedObjectContext) private var viewContext
    
@State var sorting: KeyPath = \Log.diveNr
@State var sortOrder: SortOrder = .forward
    
private var fetchRequest: FetchRequest<Log>
private var logs: FetchedResults<Log> {
    fetchRequest.wrappedValue
}
    
init() {
    fetchRequest = FetchRequest(sortDescriptors: [SortDescriptor(sorting, order: sortOrder)])
}

Can someone help me to resolve this?


SOLUTION:

@FetchRequest(sortDescriptors: [SortDescriptor(\.diveNr, order: .forward)])
    var logs: FetchedResults<Log>
    
    var body: some View {
        NavigationStack {
            List{
                if logs.count == 0 {
                    Text("no Logs found")
                }
                Button("change order") {
                    logs.sortDescriptors = [SortDescriptor(\.diveNr, order: .reverse)]
                }
                ForEach(logs){log in
                    NavigationLink(destination: DiveLogDetailView(diveNo: 1, diveSite: "Vela Garska")) {
                        DiveLogListObject(log: log)
                    }
                }
                .onDelete(perform: deleteLog)
            }
}

Upvotes: 1

Views: 590

Answers (2)

malhal
malhal

Reputation: 30549

You have to set it in body. Unfortunately @FetchRequest is either badly designed or badly documented.

    func updateSort() {
        logs.sortDescriptors = [SortDescriptor(\.diveNr, order: sortOrder)]
    }

    var body: some View {
        let _ = updateSort()
        NavigationStack {

Upvotes: 0

rob mayoff
rob mayoff

Reputation: 385500

Because of the use of @State, both sorting and sortOrder are computed properties. You cannot use a computed property in init until all stored properties have been initialized. (Otherwise, the computed property's getter might let the not-fully-initialized self escape.)

So use the underlying stored properties instead:

init() {
    let descriptor = SortDescriptor(
        _sorting.wrappedValue,
        order: _sortOrder.wrappedValue
    )
    fetchRequest = FetchRequest(sortDescriptors: [descriptor])
}

Upvotes: 1

Related Questions