Random fetch from core data - ios

I have n number of object of an entity.
I want to fetch 30, random object from the same entity.
I'm using core data, swift 3. Could anybody help me to solve this problem?
Thanks,

This is going to require an extra step, because Core Data doesn't have any built-in support for a random selection. You'll need to have some unique attribute, select your own random subset of values for that attribute, and then get the managed objects with those values.
First, you need a managed object property that has unique values. Any property will do, but numeric properties will work faster. Let's say for example you have an integer property called myUniqueID that has unique values.
Do a fetch request to get all current values of this property. You only want values of this specific property, so set the fetch result type to NSFetchRequestResultType.dictionaryResultType and set the fetch request's propertiesToFetch to include only myUniqueID. The result will be an array of dictionaries, each containing a single value of myUniqueID.
Add your own logic to choose 30 random values from this result. Collect them in an array.
Do a second fetch request, this time fetching managed objects instead of dictionaries. If your array of random IDs is called uniqueIDArray, use a predicate of something like NSPredicate(format: "myUniqueID in %#", uniqueIDArray)

Related

NSFetchRequest based on array property size

I have a NSManagedObject which has a (transformable) NSArray property arrayProperty.
I would like to execute a fetch request filtering for objects whose property size is less than 5. I tried
[NSPredicate predicateWithFormat:#"arrayProperty.#count <= 5"]
and
[NSPredicate predicateWithFormat:#"arrayProperty[SIZE] <= 5"]
but none of them work (giving Unsupported function expression count and Unsupported function [SIZE]).
Is there a way to achieve this?
This kind of thing isn't possible with transformable properties. Transformable are convenient for storing data, but once they're stored, that's all they are-- a bunch of bytes with no information about the data structure that created them. SQLite doesn't know that it's an array, so it's not able to do things like count how many items are in the array.
If you use transformable properties, you lose any ability to filter based on them, except for extremely basic tests like whether the value is nil.
If you need to do this kind of filtering, you'll need to consider how to change your data model. One possibility would be that instead of saving an array, create a new entity with a to-many relationship to store the values.

Filter NSFetchedResultsController request with predicate using computed attribute? [duplicate]

Is there a way to use a 'transient' field or something like that and in some way sort accordingly with a NSFetchedResultsController. I want to do the following:
I have location of places in a database. When a person opens the list, I want to show the nearest place on top, an then sort accordingly to distance. But clearly,this depends on the users location, so I cannot use a static field. I was hoping to use a transient field, as you can use for the section headers.
Is there anybody who can give a solution or workaround for this situation?
You cannot use a transient property in a fetch request for a SQlite base Core Data store.
See Fetching Managed Objects in the "Core Data Programming Guide":
You cannot fetch using a predicate based on transient properties
(although you can use transient properties to filter in memory
yourself). ... To summarize, though, if you execute a fetch directly, you should
typically not add Objective-C-based predicates or sort descriptors to
the fetch request. Instead you should apply these to the results of
the fetch.
You can use a transient property for sectionNameKeyPath, but even then you need a first sort descriptor for the sections that is based on a persistent attribute.
So the only workaround is probably to fetch all objects and then sort the fetched array. But then of course you don't have the advantages of a fetched results controller anymore.

CoreData doesn't keep the sequence while saveContext

I am trying to insert data in CoreData. I have may records to insert, this should be all or none. So I am creating instance of NSManagedObject and inserting it to NSManagedObjectContext one by one.
When I call below method after inserting all records:
[_myManagedObjectContext saveContext:&error];
This method save all inserted records to persistent store. When I open the Sqlite file generated by core data, I found all the records inserted by my app.
Problem is the order is not same. e.g I inserted records based on serial number 1-100 in sequense, I am able to see random sequence in CoreData sqlite file.
I know that I should not worry about the entries on core data sqlite file I can always fetch records in sorted order using NSPredicate but I need to keep the sequence because in some circumstances I need to study the database file.
Can someone tell me what to do to let saveContext method save records in the same order those are inserted to context?
The only way to reliably maintain order of your objects is to add an additional attribute on the object, such as 'index', and then set the value once the object has been created. Use this object to sort the results when you retrieve them or use the index to retrieve the objects in the required order.
The easiest way is to implement the NSManagedObject subclass's awakeFromInsert method and set a date property to NSDate(). Now you have a sequence which is accurate to 10,000th of a second. When you need items in order, just sort by this date property.

Is that possible to add a value in a core data fetch?

Suppose I have this core data structure:
code
name
address
value
is that possible to add 100 to value during the fetch? I mean, to receive a fetch results where all values are their values on the database + 100?
I know I can enumerate all results after and change the value but I am wondering if there is a way to do that while I fetch.
No, all a fetch can do is give you the literal contents of the persistent store. If you're fetching a managed object subclass you might consider adding a computed property as a category method that always returns the named field plus 100; if you're fetching dictionaries then you'll probably have to modify them yourself (which will be a hassle as they'll come back immutable).

NSSortDescriptor with a function

I only have a limited experience in using NSSortDescriptor.
It was sorting on one key and it worked fine.
But here is what I need now, I have a set of pairs of numbers, for example :
{(2,3), (44,5), (6,17), (33,7) ……(173,21)}
I want to sort the pairs (x,y) according to the value of a given function myfunction(x,y).
There is the trivial idea of making triplets (x,y,z) where z would be the computation of myfunction(x,y) and then sort the set of triplets, but this not what I want.
Is there a proper way to use NSSortDescriptor to do what I need?
Thanks for any information.
Unless you are using this sort descriptor with Core Data using a SQLite store, you could create a transient attribute on the object where the attribute represented z, the computation of your function. You could then sort on that transient attribute and it would produce the results you want, without storing the z values.
However, if you are using Core Data with a store like SQLite where the entire store contents are not read into memory, you cannot use transient attributes to sort on and you would have to either store your z values actually in the managed objects in order to achieve what you are describing, or read all of your managed objects into an array, and then sort that array of objects on the transient property... which would work OK if you only had a limited number of managed objects, but not so well otherwise.

Resources