2
votes

I have a core data model defined as follows:

A User has many events. Each event can have many pictures. The relationships have "cascade" delete rule.

I'm trying to understand how to delete local files when the entity disappears. Is there some kind of dealloc or "finalize" method that a core data entity calls before it is gone?

Each picture entity has a reference to a local file that's stored in the app's documents directory.

When the user is deleted through table view's commitEditingStyle, I can delete the images by stepping through the relationships and delete the files manually:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{

    {
        // Delete the managed object for the given index path
        NSManagedObjectContext *context = [[[RKObjectManager sharedManager] objectStore] managedObjectContext];

        AppUser* managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];

        //clean up local files before deleting the object
        [self deleteLocalContentForAppUser:managedObject];        

//now delete the object
        [context deleteObject:managedObject];

        // Save the context to remember deletion
        NSError* error = nil;
        if (![context save:&error]) {
            /*
             Replace this implementation with code to handle the error appropriately.

             abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
             */
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }

    }

}

However, when the entities are deleted through other methods, and my fetched results controller gets notified of them, the nested relationships contain no objects. The user's events set will not have any entities to step through and delete the local content. Is this the result of the "cascade" delete rule set for the relationship?

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
//    UITableView *tableView = self.tableView;
//     
    AppUser* managedObject = anObject;
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
//             [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            //             [self configureCell:[tableView cellForRowAtIndexPath:newIndexPath] atIndexPath:newIndexPath];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];


            //these methods cannot find any content to delete
            [managedObject deleteLocalImages];
            [managedObject deleteLocalContent];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[self.tableView cellForRowAtIndexPath:newIndexPath] atIndexPath:newIndexPath];

            [managedObject updateLocalImages];
            break;

        case NSFetchedResultsChangeMove:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}
1

1 Answers

4
votes

You can implement the prepareForDeletion method in your NSManagedObject subclass. It is invoked automatically before an object is deleted, so that you can also delete referenced files from there.