Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI core data, grouped list fetch result

using core data im storing some airport and for every airport i'm storing different note

I have created the entity Airport and the entity Briefing

Airport have 1 attribute called icaoAPT and Briefing have 4 attribute category, descript, icaoAPT, noteID

On my detailsView I show the list all the noted related to that airport, I managed to have a dynamic fetch via another view called FilterList

import SwiftUI
import CoreData


struct FilterLIst: View {
    var fetchRequest: FetchRequest<Briefing>
    @Environment(\.managedObjectContext) var dbContext
    
    
    init(filter: String) {
        fetchRequest = FetchRequest<Briefing>(entity: Briefing.entity(), sortDescriptors: [], predicate: NSPredicate(format: "airportRel.icaoAPT == %@", filter))
        
    }
    func update(_ result : FetchedResults<Briefing>) ->[[Briefing]]{
        return Dictionary(grouping: result) { (sequence : Briefing)  in
            sequence.category
        }.values.map{$0}
        
    }
    

        
  
    var body: some View {
       
        List{
            ForEach(update(self.fetchRequest.wrappedValue), id: \.self) { (section : Briefing) in
                Section(header: Text(section.category!)) {
                    
                    ForEach(section, id: \.self) { note in
                        Text("hello") 
/// Xcode error Cannot convert value of type 'Text' to closure result type '_'
                    }
                }
            }
        }
    }
}

on this view I'm try to display all the section divided by category using the func update... but Xcode give me this error , I can't understand why..Cannot convert value of type 'Text' to closure result type '_'

fore reference I list below my detailsView

import SwiftUI

struct DeatailsView: View {
    @Environment(\.managedObjectContext) var dbContext
    @Environment(\.presentationMode) var presentation
    @State var airport : Airport
    @State var note = ""
    @State var noteTitle = ["SAFTY NOTE", "TAXI NOTE", "CPNOTE"]
    @State var notaTitleSelected : Int = 0
    @State var notaID = ""

    
    
    
    var body: some View {
        Form{
            Section(header: Text("ADD NOTE Section")) {
                TextField("notaID", text: self.$notaID)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .padding()
                TextField("add Note descrip", text: self.$note)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .padding()
                
                Picker(selection: $notaTitleSelected, label: Text("Class of Note")) {
                    ForEach(0 ..< noteTitle.count) {
                        Text(self.noteTitle[$0])
                    }
                }
                HStack{
                    Spacer()
                    Button(action: {
                        let nota = Briefing(context: self.dbContext)
                        nota.airportRel = self.airport
                        nota.icaoAPT = self.airport.icaoAPT
                        nota.descript = self.note
                        nota.category = self.noteTitle[self.notaTitleSelected]
                        nota.noteID = self.notaID
                        
                        do {
                            try self.dbContext.save()
                            debugPrint("salvato notazione")
                            
                        } catch {
                            print("errore nel salva")
                        }
                    }) {
                        Text("Salva NOTA")
                    }
                    Spacer()
                }
            }
            
            Section(header: Text("View Note")) {
                FilterLIst(filter:  airport.icaoAPT ?? "NA")
            }
        }
    }
}

thanks for the help

like image 947
Damiano Miazzi Avatar asked Oct 26 '22 20:10

Damiano Miazzi


1 Answers

This is because you try to iterate over a single Briefing object and a ForEach loop expects a collection:

List {
    ForEach(update(self.fetchRequest.wrappedValue), id: \.self) { (section: Briefing) in
        Section(header: Text(section.category!)) {
            ForEach(section, id: \.self) { note in // <- section is a single object
                Text("hello")
                /// Xcode error Cannot convert value of type 'Text' to closure result type '_'
            }
        }
    }
}

I'd recommend you to extract the second ForEach to another method for clarity. This way you can also be sure you're passing the argument of right type ([Briefing]):

func categoryView(section: [Briefing]) -> some View {
    ForEach(section, id: \.self) { briefing in
        Text("hello")
    }
}

Note that the result of your update method is of type [[Briefing]], which means the parameter in the ForEach is section: [Briefing] (and not Briefing):

var body: some View {
    let data: [[Briefing]] = update(self.fetchRequest.wrappedValue)
    return List {
        ForEach(data, id: \.self) { (section: [Briefing]) in
            Section(header: Text("")) { // <- can't be `section.category!`
                self.categoryView(section: section)
            }
        }
    }
}

This also means you can't write section.category! in the header as the section is an array.

You may need to access a Briefing object to get a category:

Text(section[0].category!)

(if you're sure the first element exists).


For clarity I specified types explicitly. It's also a good way to be sure you always use the right type.

let data: [[Briefing]] = update(self.fetchRequest.wrappedValue)

However, Swift can infer types automatically. In the example below, the data will be of type [[Briefing]]:

let data = update(self.fetchRequest.wrappedValue)
like image 70
pawello2222 Avatar answered Nov 26 '22 15:11

pawello2222