Search code examples
iosobjective-ccore-dataentitydelete-row

Try to delete data from two entities in core data


I try to delete record from two entities. Core data has two entities,with the names Student and Detail both have an inverse relationship. Relationship is

Student -> Detail:detail Detail -> Student:student

Try to delete record from both entities from the table view. but when i try to delete, only entity Student from delete but from detail Entity can't delete. it shows me this error.

-[NSSet isSubsetOfSet:]: set argument is not an NSSet'

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source

        AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
        _mainContext = [appDelegate manageObjectContext];

        [_mainContext deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
        Detail *detailEntity = [self.fetchedResultsController objectAtIndexPath:indexPath];
        Student *studentEntity = [self.fetchedResultsController objectAtIndexPath:indexPath];

        NSMutableSet *mySet = [[NSMutableSet alloc] init];
        [mySet removeObject: detailEntity];
        [studentEntity removeDetail:mySet];
        studentEntity.detail = detailEntity;

        NSError *error = nil;
        if (![_mainContext save:&error]) {
            NSLog(@"Unresolve Error %@, %@", error, [error userInfo]);
            abort();
        }

        [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

    } 
}

StudentCoredataclass.h

#import "Student+CoreDataClass.h"


NS_ASSUME_NONNULL_BEGIN

@interface Student (CoreDataProperties)

+ (NSFetchRequest<Student *> *)fetchRequest;

@property (nullable, nonatomic, copy) NSString *name;
@property (nullable, nonatomic, copy) NSString *study;
@property (nullable, nonatomic, copy) NSString *number;
@property (nullable, nonatomic, retain) NSSet<Detail *> *detail;

@end

@interface Student (CoreDataGeneratedAccessors)

- (void)addDetailObject:(Detail *)value;
- (void)removeDetailObject:(Detail *)value;
- (void)addDetail:(NSSet<Detail *> *)values;
- (void)removeDetail:(NSSet<Detail *> *)values;

@end
NS_ASSUME_NONNULL_END

DetailCoredataclass.h

#import "Detail+CoreDataClass.h"


NS_ASSUME_NONNULL_BEGIN

@interface Detail (CoreDataProperties)

+ (NSFetchRequest<Detail *> *)fetchRequest;

@property (nullable, nonatomic, copy) NSString *address;
@property (nullable, nonatomic, copy) NSString *contact;
@property (nullable, nonatomic, copy) NSString *email;
@property (nullable, nonatomic, copy) NSString *number;
@property (nullable, nonatomic, retain) Student *student;

@end

FetchedResultController:

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    _mainContext = [appDelegate manageObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Student"];

    // Add Sort Descriptors
    [fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO]]];

    //[fetchRequest setRelationshipKeyPathsForPrefetching: @"detail"];
    // Initialize Fetched Results Controller
    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_mainContext sectionNameKeyPath:nil cacheName:nil];

    // Configure Fetched Results Controller
    [self.fetchedResultsController setDelegate:self];

    // Perform Fetch
    NSError *error = nil;
    [self.fetchedResultsController performFetch:&error];

Solution

  • replace your code with:

    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
        if (editingStyle == UITableViewCellEditingStyleDelete) {
            AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
            NSManagedObjectContext *context = [appDelegate manageObjectContext];
            Student *studentEntity = [self.fetchedResultsController objectAtIndexPath:indexPath];
            [context deleteObject:studentEntity];
             NSError *error = nil;
            [context save:&error];
        } 
    }
    

    Next set the Delete Rule in the model to delete the detail when the student is deleted (and the reverse). It is unclear to me why you have data split into two entities.

    You should not remove the tableView's Cell here. You should remove it when you get the delegate callback from the fetchedResultsController. If you haven't implemented those methods, then you do so now.