Trying to implement master-child Managed Object Co

2019-06-03 15:24发布

I am working on a project where I am doing a mass delete of a number of NSManagedObjects (MO) that I retrieve from Core Data. When I iterate through this collection of MO's, I am also retrieving OTHER MO's by calling a fetch method DURING the iteration of the initial collection of MO's.

If during this iteration process, an object is found from the fetch request, the MO is deleted. I realize that this is a poor design of the architecture, as these MO's should in fact be having inverse relationships with one another, and therefore via a cascade delete rule, all of these objects would easily be deleted. This unfortunately is not the case, and it would be too difficult to go back and make these fixes, which is why I am here.

Also, I realize that this scenario which I am describing should be using a parent-child NSManagedObjectContext to do things correct, and of course, to avoid crashes from occurring. I am unsure how to implement this given the architecture I am working with. Here is an example of the code I am working with:

- (void)massDelete {

...
       NSArray *objectsToPurge = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

       if (objectsToPurge) {

            [objectsToPurge enumerateObjectsUsingBlock:^(MyMO *mo, NSUInteger idx, BOOL *stop) {

                OtherMO *otherMO = [self fetchOtherMO:mo];

                if (otherMO) {
                    [self.managedObjectContext deleteObject:otherMO];
                }

                [self.managedObjectContext deleteObject:mo];

            }];
        }

        [self.managedObjectContext save:&purgeError];
}


    - (OtherMO *)fetchOtherMO:(MyMO *)mo {

        NSManagedObjectContext *context = [[MySingleton sharedInstance] managedObjectContext];
        NSError *error;

        // Create fetch request
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"OtherMO" inManagedObjectContext:context];
        [fetchRequest setEntity:entity];

        // Create predicate
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMO == %@", mo];
        [fetchRequest setPredicate:pred];

        NSArray *items = [context executeFetchRequest:fetchRequest error:&error];
        if ([items count]>0) {
            return [items firstObject];
        } else {
            return nil;
        }
    }

Like I said, I realize that I am using two separate NSManagedObjectContexts here, and I need to implement a Parent-Child construct, but am unsure how to do this. Given that I can't do anything about the Core Data architecture, and given this is the scenario I am working with, what would be the best solution for my problem?

1条回答
男人必须洒脱
2楼-- · 2019-06-03 16:05

I think it not require two MOC, you are able to solve it by one. Just pass it as a parameter to the fetchOtherMOByMyMo:(MyMo *)mo onContext:(NSManagedObjectContext *)context.

And you forget to use performBlock: Check, it should work without crashing:

- (void)massDelete {

...
__weak typeof(self) weakSelf = self;
self.managedObjectContext performBlock:^{
       NSArray *objectsToPurge = [weakself.managedObjectContext executeFetchRequest:fetchRequest error:&error];

       if (objectsToPurge) {

            [objectsToPurge enumerateObjectsUsingBlock:^(MyMO *mo, NSUInteger idx, BOOL *stop) {

                OtherMO *otherMO = [weakself fetchOtherMO:mo onContext:weakself.managedObjectContext];

                if (otherMO) {
                    [weakself.managedObjectContext deleteObject:otherMO];
                }

                [weakself.managedObjectContext deleteObject:mo];

            }];
        }

        [weakself.managedObjectContext save:&purgeError];
});
}

- (OtherMO *)fetchOtherMO:(MyMO *)mo onContext:(NSManagedObjectContext *)context{
        NSError *error;

        // Create fetch request
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"OtherMO" inManagedObjectContext:context];
        [fetchRequest setEntity:entity];

        // Create predicate
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMO == %@", mo];
        [fetchRequest setPredicate:pred];

        NSArray *items = [context executeFetchRequest:fetchRequest error:&error];
        if ([items count]>0) {
            return [items firstObject];
        } else {
            return nil;
        }
    }
查看更多
登录 后发表回答