arraysswiftfilterswiftuiexc-bad-instruction

SwiftUI EXC_BAD_INSTRUCTION when filtering and mapping Array


I have an Entity called Lessons, which consists of:

@NSManaged public var timeMinutes: Double
@NSManaged public var id: UUID
@NSManaged public var lessonDescription: String
@NSManaged public var date: Dates

The 'date' attribute is linked with a one-to-many relationship to a separate 'Dates' entity, which consists of:

@NSManaged public var date: Date

I am now trying to display a graph that has the summed 'timeMinutes' by 'date'. This finalArray would have the following structure:

struct FinalArray {
    let summedMinutes : Double
    let date : Date
}

My code to generate (and display) this array looks as following:

import SwiftUI
import SwiftUICharts

struct Test: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(fetchRequest: Lessons.allLessonsFetchRequest()) var lessons: FetchedResults<Lessons>

   var finalArray = [FinalArray]()

    init(){
        let allKeys = Set<Date>(lessons{$0.date.date})
        for key in allKeys {
            let sum = lessons.filter({$0.date.date == key}).map({$0.timeMinutes}).reduce(0, +)
            finalArray.append(FinalArray(summedMinutes:sum, date:key))
        }
       finalArray = finalArray.sorted(by: {$0.date < $1.date})
    }

    var body: some View {
        VStack{
               LineView(data:  finalArray.map {$0.summedMinutes}, title: "This graph returns empty").padding()
               LineView(data:  lessons.map {$0.timeMinutes}, title: "This graph works").padding()
        }
    }
}

I get the following error, on the first line of init:

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

Does anyone know how I can fix this? What is the reason for this?

If I do a ForEach on the Core Data within my view, it works OK:

var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateStyle = .long
return formatter
}

        ForEach(lessons.map {$0.date.date}, id: \.self) { item in
            VStack{
                Text("\(item, formatter: self.dateFormatter)")
            Text(String(self.lessons.filter{$0.date.date == item}.map {$0.timeMinutes}.reduce(0, +)))
            }
        }

This code works, but it's not what I want, I want to display the summed 'timeMinutes' in an Array. Any ideas or workarounds would be super welcome!


Solution

  • The lessons is fetched on view initial update, but on init it is not defined yet, so trying to use it in there you've got a crash.

    Here is possible approach:

       @State private var finalArray = [FinalArray]()
    
        var body: some View {
            VStack{
                   LineView(data:  finalArray.map {$0.summedMinutes}, title: "This graph returns empty").padding()
                   LineView(data:  lessons.map {$0.timeMinutes}, title: "This graph works").padding()
            }
            .onAppear {
               let allKeys = Set<Date>(lessons{$0.date.date})
               for key in allKeys {
                   let sum = lessons.filter({$0.date.date == key}).map({$0.timeMinutes}).reduce(0, +)
                   finalArray.append(FinalArray(summedMinutes:sum, date:key))
               }
              finalArray = finalArray.sorted(by: {$0.date < $1.date})
           }
        }