5

I'm trying to do simple fetch request of my TrainingSessionHistory (coredata object) in one of my SwiftUI View but got Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

struct TrainingHistoryView: View {

var trainingSession  : TrainingSession

init(trainingSession : TrainingSession) {
    self.trainingSession = trainingSession

    let fetchRequest = FetchRequest(fetchRequest: TrainingSessionHistory.getBy(nb: 2, myTrainingSession: self.trainingSession))
    print(fetchRequest.wrappedValue) // -> crash this EXC_BAD_INSTRUCTION

}

TrainingSessionHistoryExtension : creation of fetch request

static func getBy(nb : Int, myTrainingSession : TrainingSession) -> NSFetchRequest<TrainingSessionHistory>{
    let request:NSFetchRequest<TrainingSessionHistory> = TrainingSessionHistory.fetchRequest() as!    NSFetchRequest<TrainingSessionHistory>

    //request.predicate = NSPredicate(format: "trainingSession == %@", myTrainingSession)
    request.fetchLimit = nb

    let sortDescriptor = NSSortDescriptor(key: "date", ascending: true)

    request.sortDescriptors = [sortDescriptor]

    return request
}

I don't understand what is happen bad in the request :

po debug

Edit : Fixing

Replacing by

let req = TrainingSessionHistory.getBy(nb: 2, myTrainingSession: self.trainingSession)
        self.alternativeContext.performAndWait {
            do {
                let result = try req.execute()
                print(result)
            }catch {
                print(error)
            }
        }

where alternativeContext define in delegate look like this :

lazy var alternativeContext: NSManagedObjectContext = {
        let context = persistentContainer.newBackgroundContext()
        return context
}()

Thanks to https://stackoverflow.com/a/56359760/3596283

All work but still don't understand why "FetchRequest.wrappedValue()" method wasn't working.

Jopolaz
  • 402
  • 1
  • 3
  • 18
  • You’ve set you fetch request but you’ve not run it! Use the `do try catch` construct to run your fetch request. – andrewbuilder Jan 09 '20 at 21:25
  • I already try some thing by this way like : `let req = TrainingSessionHistory.getBy(nb: 2, myTrainingSession: self.trainingSession) self.managedObjectContext.perform { let result = try! req.execute() }` with error : ```'The fetch request's entity 0x600003c94f20 'TrainingSessionHistory' appears to be from a different NSManagedObjectModel than this context's'``` – Jopolaz Jan 09 '20 at 21:55
  • By using the `FetchRequest` SwiftUI method (according to https://developer.apple.com/documentation/swiftui/fetchrequest), I think that we don't have to execute It thanks to `wrappedValue()`... – Jopolaz Jan 09 '20 at 22:02
  • Just add fixing way ! But not SwiftUI `FetchRequest.wrappedValue()` method. – Jopolaz Jan 09 '20 at 22:36
  • I think you'll also note that `.wrappedValue()` is of type `NSFetchRequestResult`. Surely this can only be obtained after a call to `execute` a fetch request? – andrewbuilder Jan 09 '20 at 23:17
  • Yeah. You think `NSFetchRequest` need to be fetch before be passed to SwiftUI `FetchRequest` (at `FetchRequest(fetchRequest: yourNSFetchRequest)` )? – Jopolaz Jan 10 '20 at 00:15

1 Answers1

0

Because in init the FetchRequest doesn't have the managed object context it needs from the environment yet. It only has that when it is updated just before body is called.

Change to:

struct TrainingHistoryView : View {

    var trainingSession : TrainingSession
    @FetchRequest var history : FetchedResults<TrainingSessionHistory>

    init(trainingSession : TrainingSession) {
        self.trainingSession = trainingSession
        _history = FetchRequest(fetchRequest: TrainingSessionHistory.getBy(nb: 2, myTrainingSession: trainingSession))
    }

    var body: some View {
        // history is now valid
    }
}
malhal
  • 26,330
  • 7
  • 115
  • 133