R Menke
R Menke

Reputation: 8391

Core Data Many to Many, wont break relationship or moc doesn't save

I ran into some trouble with Core Data in Swift.

I am trying to remove a relationship from an object without deleting it, since it must still exist in other relationships. Basically I have albums with photos in them and these photos have thumbnails. One photo can exist in many albums and an album can have many photos.

This was working or appeared to be working before I implemented the thumbnails, although it might never have worked and the problem only showed now. At the moment it doesn't remove the relationship.

The reason I added thumbnails is because full res images were to big. At the same time I also changed my fetch requests from core data to only fetch the bare minimum and store the needed data in a Tuple. After that I reset the moc and return as much as possible to nil. Not super fast, but very light.

So is it bad to have more than one fetch request in the same function?

Thanks and sorry if this is a stupid question, maybe I just need some sleep to see what is really going on!

My method :

make a mutable set of the albums (smallest number of objects to fetch) related to a photo

remove the current album from that set

save the altered set as the relationship with other albums.


My code :

let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let moc:NSManagedObjectContext = appDel.managedObjectContext!

        let asPredicate = NSPredicate(format: "albumID = %@", albumTuple.iD)
        let asFetchRequest = NSFetchRequest(entityName: "Album")
        asFetchRequest.predicate = asPredicate
        let asResults = moc.executeFetchRequest(asFetchRequest, error:nil)!
        currentAlbum = asResults.last as Album

        var foundPhotos : NSMutableSet = currentAlbum.photos as NSMutableSet
        var foundThumbs : NSMutableSet = currentAlbum.thumbPhotos as NSMutableSet

        let tPredicate = NSPredicate(format: "thumbID = %@", thumbs[counter].iD)
        let tFetchRequest = NSFetchRequest(entityName: "Thumbnail")
        tFetchRequest.predicate = tPredicate
        let tResults = moc.executeFetchRequest(tFetchRequest, error:nil)!

        var thumbToDelete = tResults.last as Thumbnail
        foundThumbs.removeObject(thumbToDelete as Thumbnail)
        currentAlbum.thumbPhotos = foundThumbs

        let pPredicate = NSPredicate(format: "photoID = %@", thumbs[counter].iD)
        let pFetchRequest = NSFetchRequest(entityName: "Photo")
        pFetchRequest.predicate = pPredicate
        let pResults = moc.executeFetchRequest(pFetchRequest, error:nil)!

        var photoToDelete = pResults.last as Photo
        foundPhotos.removeObject(photoToDelete as Photo)
        currentAlbum.photos = foundPhotos

        moc.save(nil)

update:

i tried with and without multiple predicates and requests in the same function. Makes no difference. I tried breaking the relationship by removing an object at either end of the relationship. moc save gives no errors. The count for the object I delete goes down 1 after removing an object. If I then refresh the moc and reset it, the count goes up again by one. So for some reason the moc doesn't recognise my managed objects and doesnt break the relationship.

Am I casting something wrong? Is there a constant that should be a variable? A typo? Or is it a problem with Core Data itself? Can I scare the moc into accepting changes??

func deletePhoto () {
        let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let moc:NSManagedObjectContext = appDel.managedObjectContext!

        let asPredicate = NSPredicate(format: "albumID = %@", albumTuple.iD)
        let asFetchRequest = NSFetchRequest(entityName: "Album")
        asFetchRequest.predicate = asPredicate
        let asResults = moc.executeFetchRequest(asFetchRequest, error:nil)!
        currentAlbum = asResults.last as Album

        println("number of photos at start")
        println(currentAlbum.photos.count)

        let pPredicate = NSPredicate(format: "photoID = %@", thumbs[counter].iD)
        let pFetchRequest = NSFetchRequest(entityName: "Photo")
        pFetchRequest.predicate = pPredicate
        let pResults = moc.executeFetchRequest(pFetchRequest, error:nil)!

        var photoToDelete : Photo = pResults.last as Photo
        currentAlbum.photos.removeObject(photoToDelete as Photo)


        var error: NSError? = nil
        if moc.hasChanges && !moc.save(&error) {
            println("error")
            abort()
        }
        println("number of photos left")
        println(currentAlbum.photos.count)
    }

Upvotes: 0

Views: 224

Answers (1)

R Menke
R Menke

Reputation: 8391

Found the problem.

My NSManaged Object subclasses had the to-many relationships with an NSMutableSet type instead of an NSSet. Don't do this.

I don't know why this worked with only one many-to-many relationship and stopped working when there where two. It shouldn't have worked at all.

Upvotes: 0

Related Questions