0

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.

  • possible duplicate of http://stackoverflow.com/questions/7209941/nspredicate-with-boolean-is-not-comparing-a-boolean-to-no – RobP Apr 12 '14 at 00:04
  • Well, not really, no. My question is about an attribute on a relationship (the referenced post concerns only an entity's own attribute); further, the test that's not working is "== YES", not "== NO". – Carl F. Hostetter Apr 12 '14 at 00:11
  • maybe use ANY or ALL as per http://stackoverflow.com/questions/7064072/nspredicate-for-searching-within-relationship-entities then? – RobP Apr 12 '14 at 00:25
  • Well, since "source" is a to-one relationship (not to-many), ANY and ALL are superfluous at best. But I tried it out, and the fetch behaves exactly the same. Thanks for the suggestion, though! – Carl F. Hostetter Apr 12 '14 at 00:28
  • I don't see anything, and I imagine you just tried comparing it to 1. All I could think of is to set a breakpoint and inspect the fetch results to see what source.isSelected actually contains for each row and make sure it's what you'd expect... – RobP Apr 12 '14 at 00:35
  • I did indeed try comparing it to 1, with no difference in behavior. The output above is a result of iterating over the fetched results and printing the value of isSelected (verified by inspection in the debugger). So the fetch really is returning entities whose source.isSelected is NO; alas! And again, thanks for the consideration of my question! – Carl F. Hostetter Apr 12 '14 at 00:39

1 Answers1

0

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