UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

[Solved] SectionedFetchRequest with Coredata, grouped by Date

Forums > SwiftUI

Hi,

Disclaimer : I'm a newbie with Swift / SwiftUI, please be kind :)

I have a DatesEntity, in relationship with a TraitementEntity and a SymptomeEntity :

So each Dates could have several treatments (traitement in French) with each its hour (heureSansDates) or symptoms (symptome in French) with each its hour

I have a "Journal" like that :

where each row with "bolt.heart.fill" symbol, is a Symptom (Symptome) and each row with "pills.fill" symbol, is a Treatment (Traitement)

done with :

 @FetchRequest(sortDescriptors: [SortDescriptor(\.name)]) var symptomes: FetchedResults<SymptomeEntity>
 @FetchRequest(sortDescriptors: [SortDescriptor(\.name)]) var traitements: FetchedResults<TraitementEntity>  
  @SectionedFetchRequest<String?, DatesEntity>(sectionIdentifier: \DatesEntity.dateSansH, sortDescriptors: [SortDescriptor(\DatesEntity.dateComplete, order: .reverse), SortDescriptor(\DatesEntity.heureSansDates, order: .reverse)]) var datessectioned: SectionedFetchResults<String?, DatesEntity>
                    List {
                        ForEach(datessectioned) { section in

                            Section{
                                ForEach(section) { h in
                                    VStack{
                                        ForEach(h.symptomearray, id: \.self) { i in
                                            HStack{

                                                Image(systemName: "clock")
                                                Text(h.dateComplete?.hourFormat ?? "")

                                                Image(systemName: "bolt.heart.fill")
                                                    .foregroundColor(Color(UIColor.systemRed))
                                                Text(i.name ?? "")

                                                ForEach(h.valeursintensitesarray, id: \.self) { val in
                                                    Image(systemName: "bolt")
                                                    Text(val.value ?? "")
                                                }
                                            }
                                        }

                                        ForEach(h.traitementarray, id:\.self) { v in

                                            HStack{
                                                Image(systemName: "clock")
                                                Text(h.dateComplete?.hourFormat ?? "")
                                                Image(systemName: "pills.fill")
                                                    .foregroundColor(Color(UIColor.systemTeal))

                                                ForEach(h.quantitesarray, id: \.self) { val in
                                                    Text(String(val.value))
                                                }
                                                Text(v.name ?? "")
                                            }
                                        }
                                    }
                                }
                                .id(dates.count)
                            } header :
                            {
                                    Text(section.id ?? "")
                            }.headerProminence(.increased)

                        }
                    }

The problem is when I want to show Only treatments, sectionned by Date, I have empty sections that appears (because, even If there is no treatment for this date, there could be a symptom for this date...)

              List {
                        ForEach(datessectioned) { section in
                            Section {
                                ForEach(section) { h in

                                    ForEach(h.traitementarray, id:\.self) { v in
                                        HStack{
                                            Image(systemName: "clock")
                                            Text(h.dateComplete?.hourFormat ?? "")
                                            Image(systemName: "pills.fill")
                                                .foregroundColor(Color(UIColor.systemTeal))

                                            ForEach(h.quantitesarray, id: \.self) { val in
                                                Text(String(val.value))
                                            }
                                            Text(v.name ?? "")
                                        }
                                    }
                                }
                                .id(dates.count)

                            } header : {
                                Text(section.id ?? "") 
                            } .headerProminence(.increased)
                        }  
                    }

in : TraitementEntity+CoreDataProperties.swift I have declared :

public var datesarray: [DatesEntity] {
        let set = dates as? Set<DatesEntity> ?? []

        return set.sorted {
            $0.dateComplete! < $1.dateComplete!
        } 
    }

(for better explaination, here is the Journal for symptoms only)

@delawaremathguy tried to help me in another thread but I can't make it work, so I figured I'll make a new thread with better explaination

Any help is appreciated :)

Thanks

2      

Looking at your examples of the symptoms and treatment entries, what can I see in the text is that on every day you have at least one symptom, but not necessarily a treatment. By this I mean that every date has a symptom, so does not show an expected output, because they are show irrespective of whether or not a treatment was recorded.

Here is an example based on a sample code in the Xcode documentation for ForEach, that has been modified to only show certain fonts.

private struct NamedFont: Identifiable {
    let name: String
    let font: Font
    var id: String { name }
}

private let namedFonts: [NamedFont] = [
    NamedFont(name: "Large Title", font: .largeTitle),
    NamedFont(name: "Title", font: .title),
    NamedFont(name: "Headline", font: .headline),
    NamedFont(name: "Subheadline", font: .subheadline),
    NamedFont(name: "Callout", font: .callout),
    NamedFont(name: "Body", font: .body),
    NamedFont(name: "Caption", font: .caption)
]

struct ContentView: View {
    var body: some View {
        HStack {

// The original code was
//    ForEach(namedFonts) { namedFont in
//        Text(namedFont.name)
//            .font(namedFont.font)
//    }

            ForEach(namedFonts) { namedFont in
                if namedFont.name.contains("Ca") {  // Callout, Caption
                     Text(namedFont.name)
                        .font(namedFont.font)
                }
            }
        }
    }
}

You could create an appropriate conditional to skip empty treatments, or empty symptoms, for the dates.

2      

Thanks a lot for your answer !

I didn't know you could do that, so thanks

I finally just used a predicate in my SectionedFetchRequest and it worked

 @SectionedFetchRequest<String?, DatesEntity>(sectionIdentifier: \DatesEntity.dateSansH, sortDescriptors: [SortDescriptor(\DatesEntity.dateComplete, order: .reverse), SortDescriptor(\DatesEntity.heureSansDates, order: .reverse)], predicate: NSPredicate(format: "ANY symptomes != nil")) var datessectionnedS: SectionedFetchResults<String?, DatesEntity>

2      

Yes, you can use a predicate for the fetchRequest, and that will limit what is fetched based on the predicate.

(As an aside you may also want to learn how to use compound predicates, to use with logic such as AND & OR, but that is entirely up to you, and whether you may need it in future).

Looking at your buttons (Tout, Symptomes and Traitement) and the examples you presented, I thought that you wanted to dynamically filter the values for the view, using data that you had already extracted.

It is your app, either way works, so whatever works for you is great.

3      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.