0

I have an entity called Task which has a to-one relationship with the entities TaskTemplate and Occurrence. Both of these entities have to-many relationships with Tasks. Deletion rules are set to Nullify.

Within an Occurrence, I try to remove all Tasks. To do that, I use the following code:

- (bool)removeAllTasks
{
    NSMutableSet *tasks = [self mutableSetValueForKey:@"tasks"];
    [tasks removeAllObjects];
    return YES;
}

This does not work. Here are Task and Occurrence before the attempted removal:

Relationship 'tasks' on managed object (0x1006bd1c0) <Occurrence: 0x1006bd1c0> (entity: Occurrence; id: 0x102119510 <x-coredata://6A0ECEF9-473D-44B2-9E89-AC15179D7761/Occurrence/p1> ; data: {
    ... bunch of properties ...
    taskType = "0x10211a020 <x-coredata://6A0ECEF9-473D-44B2-9E89-AC15179D7761/TaskTemplate/p2>";
    tasks =     (
        "0x1021185e0 <x-coredata://6A0ECEF9-473D-44B2-9E89-AC15179D7761/Task/p3>"
    );
}) with objects {(
    <Task: 0x10c31d700> (entity: Task; id: 0x1021185e0 <x-coredata://6A0ECEF9-473D-44B2-9E89-AC15179D7761/Task/p3> ; data: {
    ... some more properties ...
    occurrence = "0x102119510 <x-coredata://6A0ECEF9-473D-44B2-9E89-AC15179D7761/Occurrence/p1>";
    persons = "<relationship fault: 0x10e049e90 'persons'>";
    startDate = "2013-01-28 11:00:00 +0000";
    type = "0x10211a020 <x-coredata://6A0ECEF9-473D-44B2-9E89-AC15179D7761/TaskTemplate/p2>";
})
)}

... and this is the result after -removeAllObjects:

Relationship 'tasks' on managed object (0x1006bd1c0) <Occurrence: 0x1006bd1c0> (entity: Occurrence; id: 0x102119510 <x-coredata://6A0ECEF9-473D-44B2-9E89-AC15179D7761/Occurrence/p1> ; data: {
    ... bunch of properties ...
    taskType = "0x10211a020 <x-coredata://6A0ECEF9-473D-44B2-9E89-AC15179D7761/TaskTemplate/p2>";
    tasks =     (
    );
}) with objects {(
)}

Notice that the tasks relationship is now empty, as I would expect it to be. But I would also expect taskType to be empty. What am I doing wrong?

EDIT:

I changed the code so I can see if the task is marked as deleted. I have now:

- (bool)removeAllEvents
{
    NSMutableSet *tasks = [self mutableSetValueForKey:@"tasks"];
    [tasks enumerateObjectsUsingBlock:^(Task *task, BOOL *stop)
     {
    if (![task isDeleted])
         [self.managedObjectContext deleteObject:task];
         NSLog(@"Deleted %@", [task isDeleted] ? @"Y" : @"N");
     }];
    [self.managedObjectContext processPendingChanges];
    return YES;
}

It does show 'Y', to indicate that the task is marked for deletion. A fetchRequest shows me that there are no tasks left in the context. But if I try to save, I get an inconsistency message ("tasks is not valid").

Carelinkz
  • 936
  • 8
  • 27
  • Using something like `[self.managedObjectContext deleteObject:aTask];` for every task in the *Occurrence* works, but why doesn't the `-removeAllObjects` method? I'd think it would Just Work (tm). – Carelinkz May 23 '13 at 10:36

1 Answers1

2

Your removeAllTasks method does not delete any objects. It only removes the relationships from the Occurrence object to the Task objects, but the tasks continue to exist. The deletion rules are only applied if an object is deleted (using deleteObject:).

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • I am not yet real comfortable with core data, so please forgive a silly further question: I am using the `deleteObject:` method now, but printing [anOccurrence tasks] shows a faulted task, instead of nothing. I deleted the task, so why is it not gone? This is even after a `-processPendingChanges`... – Carelinkz May 23 '13 at 11:46
  • 1
    @markjs: `deleteObject:` removes the object from the store, but as long as you have a pointer (a "strong reference") to the object that objects continues to exist in memory. Fetching any attributes of the deleted object will fail, but `isDeleted` will return YES. - I hope that makes sense, it is a bit difficult to explain. – Martin R May 23 '13 at 11:59
  • It does. So to delete the Tasks I should iterate through all relationships that the Occurrence has, and use `deleteObject` on it. When done, I should then be able to safely save the data file, without inconsistencies. Correct? – Carelinkz May 23 '13 at 12:09
  • Does not work. If I request the Tasks in the context using a fetch request, I get nothing (correctly, I think). But when I print the number of items in the NSMutableSet occurrence.tasks, I get one item (it's a fault). This item messes up the save; I get an inconsistency. It's driving me nuts :( – Carelinkz May 23 '13 at 22:05
  • @markjs: Perhaps you have set a "Minimum Count" for the tasks relationship? – Martin R May 24 '13 at 05:17
  • Thanks Martin, I did. So I removed the minimum count. It still does not solve the problem. I'll keep on digging! – Carelinkz May 24 '13 at 16:18
  • @markjs Be careful if you have an `ordered to-many` relationship, it is highly bugged... @MartinR I don't agree that you should remove "by hand" the object to delete from all the relationships, or at least, `Core Data` is supposed to do it for you, normally... I have opened a related question on this matter : http://stackoverflow.com/questions/17158091/deleting-wont-nullify-until-save-is-it-true – Colas Jun 17 '13 at 22:59
  • @Colas: I did not say that you *"should remove by hand the object to delete from all the relationships"*. I only said that removing an object from a relationship does not delete the object and therefore the deletion rules are not applied. – Martin R Jun 18 '13 at 06:51
  • @MartinR Yes, but the problem is that `deleteObject` doesnt remove the object from the relationships. – Colas Jun 18 '13 at 08:37