Search code examples
core-dataattributesnspredicaterelationshipnsfetchrequest

NSFetchRequest with to-one relationship attribute == YES predicate incorrectly fetches every entity


I have a model entity called "IRCSessionEntry", which has a to-one relationship named "source" to an entity that has a Boolean attribute named "isSelected".

When I execute the following fetch request:

NSPredicate *sourceIsSelectedPredicate = [NSPredicate predicateWithFormat:@"source.isSelected == YES"];
NSFetchRequest *selectedDataSourcesFetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"IRCSessionEntry"];
selectedDataSourcesFetchRequest.predicate = sourceIsSelectedPredicate;
NSSortDescriptor *descendingStartDateSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"startDate" ascending:NO];
selectedDataSourcesFetchRequest.sortDescriptors = @[descendingStartDateSortDescriptor];

the results incorrectly include every IRCSessionEntry, whether their source isSelected is YES or not:

Fetched sessionEntry: source Foo isSelected = 1
Fetched sessionEntry: source Foo isSelected = 1
Fetched sessionEntry: source Bar isSelected = 0
Fetched sessionEntry: source Bar isSelected = 0
Fetched sessionEntry: source Bar isSelected = 0
Fetched sessionEntry: source Bar isSelected = 0

Do I have the syntax for testing the value of a Boolean attribute on a to-one relationship wrong? If so, can someone fill me in on how to write this predicate?

If not, is anyone else having this problem?

I'm running the just-released Xcode 5.1.1 with the iOS 7.1 SDK.

Thanks!

Carl

P.S.: Additional info: the "source" entity also has a String "name" attribute; and when I change the to-one relationship predicate format string to

[NSPredicate predicateWithFormat:@"source.name == %@", @"Foo"]

the fetch correctly results only in the entities whose source.name is "Foo". So it seems to me that either:

1) I have the syntax for a to-one relationship's boolean attribute value predicate wrong; or 2) Something has broken in iOS 7(.1) with to-one relationship's boolean attribute value predicates.


Solution

  • OK, I figured out what is happening (and should have thought of it sooner). Turns out the behavior is due to a race condition. Even though the "source.isSelected" attribute of the relationship is being toggled on the main thread, and even though my fetch which is supposed to get the new set of selected sources is also being executed on the main thread, for some reason the change in "source.isSelected" hasn't propagated before the fetch is executed. In other words: race condition. If I insert a context save before I execute the fetch, everything works properly.

    So I'm going to see if I can't figure out how to manage the change-then-fetch process differently and so avoid doing a complete context save before executing the fetch. In any event, at least now it makes some kind of sense!

    I'm going to leave this query up in case someone else gets themselves into a similar situation, and this gives them the answer!

    And thanks again to RobP for giving this so much thought!

    Carl