KvdLingen
KvdLingen

Reputation: 1344

understanding adding predicate to NSFetchrequest in swift

I want to store some data downloaded from a remote file in CoreData. his data may already have been downloaded before and then the changes need to be added to core data. I use the code displayed here. In three places I use a Fetchrequest to check if the data is already in the database. I use a predicate with the request. In the code I added comments to distinguish between them. If the item is already in coreData I update the data, else I instantiates a new item. The code to add the item to core data is in a convenience init in the class. This works fine. The problem I am getting is this: The first time in this code id equals 0 so the schoolFetch is performed. Adding the predicate nr 1 gives no error and the school class is instantiated with its id set to 0. Second time id = 1. This means a locationItem, with location being a part of the school, is checked for and instantiated. To add the location to the school a fetchrequest is performed to get the schoolInstance. Predicate 2 is used. This gives no error although the previous added schoolInstance is not retrieved, but it is if the predicate is not used (commented out). After the schoolInstance is retrieved I use a fetchrequest to check if the location is already in coredata. If not it is instantiated, else its data is updated. The predicate nr 3 gives a run-time error stating nothing but EXC_BAD_ACCESS (code=1, address = 0x1). No error description is given in the debugger window. So I have two questions: a) why does predicate nr 2 not return the previous inserted item? b) why does predicate nr 3 give an error?

I structured this code this way as it is possible to first receive the information on the location and after that the information on the school.

if id == 0 {
        //get school
        let schoolFetch = NSFetchRequest<StreekgidsSchool>(entityName: "School")
        schoolFetch.predicate = NSPredicate(format: "locationId == %@", id) // predicate 1

        do {
            let fetchedSchool = try streekgidsModel?.context.fetch(schoolFetch)
            if let school = fetchedSchool?.first{
                school.name = name
                school.locationId = id
                school.colorValue = color
                schoolInstance = school
            }
            else {
                //create new entry in coredata for school
                schoolInstance = StreekgidsSchool(name: name, context: (streekgidsModel?.context)!)
                schoolInstance?.locationId = id
                schoolInstance?.colorValue = color
            }
        } catch {
            fatalError("Failed to fetch Schooldata: \(error)")
        }
    }
    else {
        //check if school already is defined
        let schoolFetch = NSFetchRequest<StreekgidsSchool>(entityName: "School")
        schoolFetch.predicate = NSPredicate(format: "locationId == %@", 0) //predicate 2

        do {
            let fetchedSchool = try streekgidsModel?.context.fetch(schoolFetch)
            if let school = fetchedSchool?.first{
                schoolInstance = school
            }
            else {
                //create new entry in coredata for school
                schoolInstance = StreekgidsSchool(id: 0, context: (streekgidsModel?.context)!)
            }
        } catch {
            fatalError("Failed to fetch Schooldata: \(error)")
        }
        //get location
        let locationFetch = NSFetchRequest<StreekgidsLocation>(entityName: "Location")
        locationFetch.predicate = NSPredicate(format: "locationId == %@", id) //predicate 3

        do {
            let fetchedLocation = try streekgidsModel?.context.fetch(locationFetch)
            if let location = fetchedLocation?.first{
                location.name = name
                location.locationId = id
                location.colorValue = color
                location.school = schoolInstance
            }
            else {
                //create new entry in coredata for location
                let locationInstance = StreekgidsLocation(name: name, context: (streekgidsModel?.context)!)
                locationInstance.locationId = id
                locationInstance.colorValue = color
            }
        } catch {
            fatalError("Failed to fetch Schooldata: \(error)")
        }

    }

Upvotes: 2

Views: 1254

Answers (1)

Magnas
Magnas

Reputation: 4054

Exactly. The %@ is expecting a Foundation object as the argument but an Int is not an object. So your id (set to zero) is being interpreted as nil. That is also why your predicate 2 is returning nothing and why you retrieve the result when you comment it out. Only your third predicate throws a run-time error but in fact all three of your predicates are working incorrectly, the first two are simply not falling over in an immediately visible way. Have you tried substituting %@ for %d.

And as you point out %u for unsigned integers.

Upvotes: 3

Related Questions