I have a search bar and some filters in my app that create two predicates. One for the string in the search bar and one for the filter (UISegmentedControl).
When the predicates are used and I insert one object into the context and then call -save: the app crashes with:
CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. Can't use in/contains operator with collection 1379410732 (not a collection) with userInfo (null)
at the point of saving:
This does not happen when the predicates are not used.
Can I somehow remove the predicates during the process of saving? I already tried it by getting the NSFetchRequest, but I cannot set it back to the controller then.
Edit
I also tried to add self as an observer on the NSManagedObjectContextDidSaveNotification and then use -mergeChangesFromContextDidSaveNotification: like one discussion on SO suggested. This didn't help either.
I found my problem. It was quite easy, but the error message was so confusing that I didn't look at the right point.
The problem was that I was using [NSPredicate predicateWithFormat:#"number CONTAINS[cd] %#", string].
So the predicate was using CONTAINS on a NSNumber. The confusing part is that the predicates are working when querying existing data from the database. I still don't understand this part, but it's working now with == comparator.
Related
Wonder if anyone can see the obvious thing I seem to be missing here. I'm working on an app that uses a variety of Core Data entities. These entities store references to a variety of other source files. I want the availability/visibility of the Core Data objects to mirror the availability of the source files.
So at launch, I iterate through the sources and if available I add the NSManagedObjectID of any associated CD objects to an NSMutableSet, lets call it availableObjectIDs.
My understanding is that the using the predicate
"self IN..."
for Core Data should evaluate based on objects IDs, so in my fetch query I use the NSPredicate
"self IN %#", availableObjectIDs
This doesn't seem to be working properly. When I fetch objects with entity X, it returns objects whose objectID has not been added to availableObjectIDs. I can evaluate the results using
[availableObjectIDs contains:object.objectID]
and some will return false, even though the predicate should be filtering them out!
Stranger still, the identical predicate does appear to work when fetching entity Y. I cannot see any difference in the entity configurations to explain this. I've tried using an NSComparisonPredicate instead, and it seems to be behaving the same way.
Baffled by this seemingly simple issue. Anyone run into something similar?
I am playing with an app that uses Core Data and NSManagedObjects to populate a UITableView. There is only one class in my application, called Event. I have created the following custom instance method on Event:
- (BOOL)isExpired {
return ([[self.endOn dateAtEndOfDay] timeIntervalSinceNow] < 0);
}
I would like to limit the UITableView that displays Event objects to only the Events that are expired - that is, where isExpired returns YES. I have tried to do this by adding an NSPredicate to the NSFetchRequest:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary * bindings) {return([evaluatedObject isExpired]);}];
[fetchRequest setPredicate:predicate];
but I get the error: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Problem with subpredicate BLOCKPREDICATE(0x272ac)'
***. Does this mean that you can't use a block predicate with an NSFetchRequest? Or have I just constructed it improperly?
Thank you!
So, it appears that we've established in the comments to the original post that this is likely caused by SQLite stores being incompatible with block predicates, since Core Data cannot translate these to SQL to run them in the store (thanks, JoostK).
There might be a couple of ways to overcome this:
Provided that the end date of your entities is a regular attribute, you might be able to express the expiry constraint as a predicate format string instead of a block predicate, which Core Data should be able to translate into a SQL clause.
If the above is possible, you will probably prefer to use a fetch request template to retrieve the expired items. You would need to pass in a substitution variable like $NOW to give access to the current date, though. This has the advantage of making the predicate template show up in the model editor.
Both approaches, however, have the disadvantage of duplicating existing functionality (i.e., your isExpired method). So another way would be fetch all qualifiying entities regardless of their expiry state first, and then run a dedicated filtering step on the resulting set of entities to weed out the non-expired ones. Since by that point, they have been fully resurrected from the store, you should be able to use a block predicate for this.
You can do a normal fetch request without specifying the predicate, and afterwards filter the resulting array:
NSArray *allEvents = [context executeFetchRequest:fetchRequest];
if (!allEvents) { // do error handling here
}
NSArray *expiredEvents = [allEvents filteredArrayUsingPredicate:predicate];
I am getting this Unsupported predicate error, while trying to instantiate a
NSFetchedResultsController with an aggregate Predicate.
My Coredata structure looks like this - There is a PurchaseDetails Entity which has n number of Payment Entity (One to many relationship). Each Payment has a type, for eg.Cash, Cheque , Other etc. Now I need to get the list of all the PurchaseDetails where Payment.type = Cash.
The NSPredicate looks like this: #"ALL payments.type = 'cash'"
Are we not supposed to use ALL ?
The predicate isn't crashing on creation rather it crash while executing the fetch request.
But the same fetch request works fine when used separately without using a NSFetchedResultsController. They both wont work together ?
Yes you need to use ALL if payments is a to-many relationship. Note that this means that every single payment's type will be #"cash". If you just want at least one cash payment, use ANY.
The (null) in the error message hints at something else though. Did you attach the predicate to the fetch request?
Also, did you try to set cache:nilin your fetched results controller? The FRC could be the reason you get stale results.
I'm facing this strange issue when trying to fetch some objects after their objectID. The error complains that there is no such thing as an objectID key path, but the managed object should respond to that. The error is not thrown all the time, which makes me think it could be a concurrency problem, although I've double checked and each context performs the operations on its own thread.
Here is the predicate, although it looks sane to me:
[NSPredicate predicateWithFormat:#"objectID == %#", book.objectID]
Edit: Regarding this answer. I didn't tried using the object itself, I need to use the objectID because of multithreading considerations.
The answer given in THIS link still holds here.
It holds in the sense that you use the same predicate:
NSPredicate* p = [NSPredicate predicateWithFormat:#"SELF = %#",book.objectID];
But you supply the objectID as parameter.
CoreData allow comparison of objectIDs and objects when fetching from the store. it probably has to do with the fact that an objectID is used for a one-to-one mapping to a managed object (hence the use of SELF which is a predicate reserved word and not a property name).
I have an NSFetchedResultsController displaying "places" in a table view, but when I update the set of places that should be displayed in another view controller, my FRC does not update the table view.
That's the general problem. My specific case seems to revolve around the NSPredicate backing my FRC, because when I remove the NSPredicate (and just get all places), everything works fine.
My query is
#"ANY photos.isFavorite == %#", [NSNumber numberWithBool:YES]
places have a one-to-many relationship with photos (I am working through CS193P). Perhaps my FRC is not set up to observe changes in a related table or something?
A bit of additional information about my situation:
My Core Data updates and queries seem okay, as my "places" table is always correct when I first load the application.
My FRC does update rows that are already present at application load. It just won't insert new rows/sections at runtime.
I am only using a single MOC.
My sectionNameKeyPath is not set to a transient attribute.
My cacheName is set to nil.
I don't know if it's your case but I'll post anyway. Maybe it could be a valid workaround.
NSFetchedResultsController pitfall
Hope it helps.
Did you try testing a simpler predicate, for example using a photo one-to-one relationship instead of photos?
"my FRC does not update the table view" - Are you using -controllerDidChangeContent: ? Did you verify it is not getting called? I've seen that contrary to the documentation, calling reloadData on the tableView from within this method is unsafe, since the method may be called on a secondary rather than the main thread.
Are you performing all operations related to the MOC on the same (main?) thread?
Try this predicate instead?
#"%# IN photos.isFavorite", [NSNumber numberWithBool:YES]