Core Data fetch by property count - core-data

I'm trying to fetch just objects that has a nsset inside bigger then 0 in core data
Something like
fetch all objects that object.set > 0
Does anyone know if this is possible?
Thanks

I was able to find a way that works:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"set.#count > 0"];
If there's a better way, please let me know, I'm posting here to help anyone that has the same problem.
Thanks

Related

CoreData with #FetchRequest (SwiftUI) and NSPredicate crashes if there is no data

I have a SwiftUI app where I am using #FetchRequest along with a predicate. Everything works fine as long as there is already some data.
However, when the app is first installed and the user tries to perform a search before entering any data, the app crashes with this error:
error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x60000188c380> , unimplemented SQL generation for predicate : (username CONTAINS[cd] "r") with userInfo of (null)
I believe the cause of the problem is that the column doesn't exist (because there is no data). What I'd like to do is pass nil for the predicate in the case where this is no data.
I understand how to use NSManagedObjectContext and count(for:) but the context isn't really made available via the #EnvironmentObject at the time I need to use it. Does anyone have any suggestions as to how to handle this. I don't see how a try-catch would work either.
Thanks.
Well, I do have a solution. Its not pretty, but it does work. Because the NSManagedObjectContext is being passed around via #Environment it isn't initialized when a SwiftUI View init is being run. So to get the context you can do:
if let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext {
and make the call to get the count in there.
So I'm clueless sometimes. I did not read the error thoroughly since it happened in the context of something I was changing so I thought the problem was that. But no, that is not the problem.
The problem is that earlier in the day, I renamed a column from username to something else. But I forgot to change the NSPredicate.
So for the sake of anyone else using SwiftUI and #FetchRequest, if you do need to count the number of items, you will need to revert to NSFetchRequest to do it. Sorry for wasting anyone's time.

Bizarre Core Data behavior when fetching unsaved data

I have a Core Data importer that loops through data, and ignores duplicate records during the import process.
But I have discovered that my NSFetchRequest is not matching against recently stored records that have not been saved. And I am seeing seemingly identical queries delivering different and unexpected results.
For example, in my testing, I discovered that this query matches and returns results:
fetchTest.predicate = [NSPredicate predicateWithFormat:#"%K = 3882", #"intEmployee_id"];
But this seemingly identical one does not:
fetchTest.predicate = [NSPredicate predicateWithFormat:#"%K = %#", #"intEmployee_id", #"3882"];
But - they both match identically after the context is saved to the persistent store.
Apple's documentation says that fetches should work against pending changes by default, and indeed I have conformed that [fetchTest includesPendingChanges] = YES.
Any ideas what on earth is going on here? How is it possible that those two fetches return different results?
Maybe the employee id is not a string but a number? Then the predicate should be:
[NSPredicate predicateWithFormat:#"%K = %#", #"intEmployee_id",
[NSNumber numberWithInt:3882]];
This would imply that the erratic behavior comes from mixing up the types. It still works somehow, even if erratically, because in the SQLite docs it says that SQLite actually does not really distinguish by type when storing the data physically.
See Distinctive Features of SQLite from the SQLite web site, under the heading Manifest Typing.
These actually don't evaluate to the same value.
[NSPredicate predicateWithFormat:#"%K = 3882", #"intEmployee_id"]
evaluates to intEmployee_id = 3882 while
[NSPredicate predicateWithFormat:#"%K = %#", #"intEmployee_id", #"3882"]
evaluates to intEmployee_id = "3882"
Try using a number instead of a string for the id.

NSPredicate fetch Core Data objects with dates attribute within NSDate date range

I'm using an NSPredicate with a couple of <= constructs to fetch objects from a Core Data store with a startDate attribute between 2 dates but I'm getting 0 objects fetched.
Here's my NSPredicate:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"( ( %# <= %K ) && ( %K <= %# ) )", fromDate, #"startTime", #"startTime", toDate];
Here's the console output:
predicate: CAST(336261600.000000, "NSDate") <= startTime AND startTime <= CAST(339285599.000000, "NSDate")
[sectionInfo numberOfObjects]: 0
Here are the dates that are in Core Data (the Attribute Type is set to Date):
startTime
---------
337249800
337309200
337318200
fromDate and toDate are both NSDate objects. I've tried substituting these with distantPast and distantFuture to make completely sure than my Core Data startTime attributes are within the date range and I still get 0 object fetched.
I have no idea why 0 objects are returned. Can anyone see where I'm going wrong?
I'd start by adding the following executable argument:
-com.apple.CoreData.SQLDebug 1
This is going to spew a gigajazillion lines of debugging information to the console when you run your app, but it should also include information about the predicate its attempting to translate to SQL, and perhaps even why it's not working.
You'll obviously want to turn remove this before shipping your app :)
After looking at the generated SQL queries it appeared like the TIMESTAMP was being evaluated as a string and not an integer. This explained why my predicate wasn't working. I confirmed this by running the following SQL query on the SQLite db that I'm using to pre-populate Core Data.
SELECT DISTINCT typeof(ZSTARTTIME) FROM ZMATCH;
This showed that the TIMESTAMP field was of type BLOB!
Adding '+0' to my predicate so the startTime attribute was evaluated as an integer fixed the issue. However this seemed like a nasty solution. Also keeping the dates stored as blobs would most likely cause issues further down the road. So I went back and re-populated the the SQLite db from scratch making sure the TIMESTAMPs were inserted as integers and not strings. Now everything is working fine.
However this does mean that I'm going to have to do some more work with the next app update because I'll have to make sure the update overwrite the old SQLite db in the Documents folder with the new db. Is there a easy way to do this? Should I look at Core Data store migration??

Using Where With SubSonic Collection

I am having problem with collection object. Here is the code
CarCollection obj=new CarCollection();
obj.Where("Id","10");
obj.Load();
The problem is the result of the records doubles i.e actually there is only 1 record with the id 10 but it returns 2 same records. Please Help me as i am a newbie.
Thanks
You should be able to do this with the following query:
CardCollection cards = new Select()
.From(Card.Schema)
.Where(Card.IdColumn).IsEqualTo(10)
.ExecuteAsCollection<CardCollection>();
I'd suggest you have a look at the query docs to see some examples of SubSonic queries:
http://subsonicproject.com/docs/Simple_Query_Tool

Fetching relations with Core Data

I have two managed objects which have a bidirectional relationship.
It is a 'segmentWithDetails' which contains a 'segment' object.
I use
NSEntityDescription *entity = [NSEntityDescription entityForName:#"SegmentWithDetails"
inManagedObjectContext:connectionDetailsService.connectionDetailsContext];
[fetchRequest setEntity:entity];
to get my segmentWith Details. This works ok.
BUT, when I try to retrieve the contained segment, I get nil.
I've tried to get it with
Segment *segment = [segmentWithDetails valueForKeyPath:#"segment"];
and with
Segment *segment = segmentWithDetails.segment;
But this does not work (=nil). I've also tried modifying the NSFetchedResultsController.
I added the following:
[fetchRequest setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObject:#"segment"]];
[fetchRequest setIncludesSubentities:YES];
But both of these do not seem to make any difference.
From what I understand out of Apple fine documentation, the relationship should just work using faults.
What am I missing here?
How do I get to the relationship object 'segment' from 'segmentWithDetails' ??
It should just work like you describe. Are you sure the "segment" object/relation actually exists and contains a real object? Check the data model that this relation isn't optional and check your code that you have actually stored something.
Problem solved.
It was not how I read the data, but how I put it in CoreData.
The posted code above is indeed correct. Thanx for the response Jaanus.

Resources