0

I have Core Data Entities Person and Boundary. They have a many-to-many relationship (each person can have many boundaries, and each boundary can have many persons).

I am trying to create a list of what boundaries Person Fred doesn't have a relationship too.

Person *person = [Person MR_findFirstByAttribute:@"name" withValue:@"Fred"];
DLog(@"person.boundaries.count: %d", person.boundaries.count);

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY persons != %@", person];

DLog(@"testBoundaries.count: %d", [Boundary MR_countOfEntitiesWithPredicate:predicate]);

I have 47 boundaries in the database, and Fred can see all 47. So I expect my fetch to return 0:

DEBUG | -[LoginViewController viewDidLoad] | person.boundaries.count: 47
DEBUG | -[LoginViewController viewDidLoad] | testBoundaries.count: 47

What is wrong with my predicate?

Padin215
  • 7,444
  • 13
  • 65
  • 103

2 Answers2

3
[NSPredicate predicateWithFormat:@"ANY persons != %@", fred]

finds all objects that are related to any person other that Fred. What you want is

[NSPredicate predicateWithFormat:@"NOT(ANY persons = %@)", fred]

and this should return all objects that are not related to Fred.

However, there seems to be a Core Data bug that "NOT ANY" or "NONE" do not work correctly in a predicate, compare NSPredicate Aggregate Operations with NONE. The workaround is to use a SUBQUERY:

[NSPredicate predicateWithFormat:@"SUBQUERY(persons, $p, $p == %@).@count == 0", fred]
Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Actually I did not yet test if the Bug has been fixed in iOS 7, so "NOT ANY" might be worth a try ... – Martin R Oct 31 '13 at 21:13
  • This did it! The subquery worked. Thank you again Martin! Man, I wish I could buy you a beer for all the times you've helped me out. – Padin215 Oct 31 '13 at 21:13
  • No. the `NOT ANY` would return 46 boundaries for some odd reason. – Padin215 Oct 31 '13 at 21:14
  • When using fred + another person, this doesn't work. So fred + sally returns all that do not include fred or sally AND any records that include just fred + sally. @MartinR –  Nov 01 '17 at 15:44
  • @MartinR as we discussed here https://stackoverflow.com/a/47001325/1951992 changing to 'in' does the trick in this case. [NSPredicate predicateWithFormat:@"SUBQUERY(persons, $p, $p in %@).@count == 0", [fred, sally]] –  Nov 01 '17 at 15:56
  • @robdashnash: Here OP asked for all objects which are not related to a given (single) person "Fred". – Martin R Nov 01 '17 at 16:07
0

you need to ask first in Class Boundary if there is a person called Fred that has boundaries. It should be something like:

NSFetchRequest* fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Boundary"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"ANY persons.name != %@", person.name];

That will fetch all the boundaries that Fred doesn't have.

Gabriel Goncalves
  • 5,132
  • 3
  • 25
  • 34