NSFetchRequest fetch object with next closest string attribute - ios

Say I have 5 Alphabet objects with an attribute letter of the given letter (of type String) persisted to Core Data.
Alphabet.letter = "A"
Alphabet.letter = "M"
Alphabet.letter = "G"
Alphabet.letter = "T"
Alphabet.letter = "D"
I can get them sorted with the following:
let alphabetFetch = NSFetchRequest(entityName: "Alphabet")
let alphabetSort = NSSortDescriptor(key: "letter", ascending: true)
Alphabet.letter = "A"
Alphabet.letter = "D"
Alphabet.letter = "G"
Alphabet.letter = "M"
Alphabet.letter = "T"
Now I want to retrieve only the Alphabet object with the closest following letter value after "G" (in this example I want to retrieve the Alphabet object with the letter attribute value "M"). How would I construct a fetch request to most efficiently fetch this object?

In addition to the sort descriptor, add a predicate and a fetch limit
to the request:
let request = NSFetchRequest(entityName: "Alphabet")
request.sortDescriptors = [ NSSortDescriptor(key: "letter", ascending: true) ]
request.predicate = NSPredicate(format: "letter > %#", "G")
request.fetchLimit = 1
The fetch request returns an array with a single element which
is the first matching object (according to the sort descriptor), or an empty array if no such element
exists.

Create an NSFetchRequest with a predicate to filter items > "G" and sort ascending.
let letter = "G"
let letterRequest = NSFetchRequest(entityName:"Alphabet")
letterRequest.predicate = NSPredicate(format: "letter > %#", letter)
letterRequest.sortDescriptors = [NSSortDescriptor(key: "letter", ascending: true)]
letterRequest.fetchLimit = 1

Related

Sort items sequentially using Core Data Swift [duplicate]

This question already has answers here:
#FetchRequest + case-insensitive sorting - SwiftUI & CoreData
(1 answer)
NSSortDescriptor in Swift
(7 answers)
Closed 1 year ago.
I want to sort items in sequence order as you can see in screenshot attached. To sort by last word in its name. Eg. Part 1, Part 2,...etc.
let request : NSFetchRequest<DisplayHelper> = DisplayHelper.fetchRequest()
print("type set is : \(type)")
let predicate = NSPredicate(format: "type == %#", type)
request.predicate = predicate
let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
let sortDescriptors = [sortDescriptor]
request.sortDescriptors = sortDescriptors

How to use NSPredicate to filter an array stored in CoreData?

I have a 'tags' array stored in CoreData (type 'Transformable') as an Array.
I am making a request to CoreData to retrieve tags based on a searchText (string) input.
How can I use NSPredicate to filter the tags array based on the searchText?
let request = NSFetchRequest<NSFetchRequestResult>(entityName: Constants.Trip)
if(searchText != nil && searchText != "") {
request.predicate = NSPredicate(format: "ANY %# in tags", searchText!)
}
request.returnsObjectsAsFaults = false
You cannot do that. Check this answer core data array of string filter
You might consider to have an entity for tags, or join the array of tags and have it as a whole string in your current entity, thus having the tags property as type String. For the last approach, you could search with the predicate below.
NSPredicate(format: "tags CONTAINS[cd] %#", searchText)
The [cd] expression is to specify case and diacritic insensitivity respectively.
You can get know more about the Core Data operations here.
I got some basic operators from the documentation and put them below:
BEGINSWITH
The left-hand expression begins with the right-hand expression.
CONTAINS
The left-hand expression contains the right-hand expression.
ENDSWITH
The left-hand expression ends with the right-hand expression.
LIKE
The left hand expression equals the right-hand expression: ? and * are allowed as wildcard characters, where ? matches 1 character and * matches 0 or more characters.
You need to write predicate and set as a part of request like this ...
func getEntitiesWithName(_ entityName:String, sortKey:String?, predicate: NSPredicate?, ascending:Bool, context:NSManagedObjectContext) -> [NSManagedObject] {
var results:[NSManagedObject] = [NSManagedObject]()
context.performAndWait { () -> Void in
let request = NSFetchRequest<NSFetchRequestResult>()
request.entity = NSEntityDescription.entity(forEntityName: entityName, in: context)
if let fetchPredicate = predicate {
request.predicate = fetchPredicate
}
if let key = sortKey {
let sortDescriptor = NSSortDescriptor(key: key, ascending: ascending, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))
request.sortDescriptors = [sortDescriptor];
}
results = (try! context.fetch(request)) as! [NSManagedObject]
}
return results
}
And you can set predicate like this
let predicate = NSPredicate(format: "isActive == %#", NSNumber(value: true as Bool))

Search core data for closest value

Currently we have a database of multiple values for r,g,b, split into own attributes. ex:
r = type float
g = type float
b = type float
There will be multiple values for each r, g, and b attribute.
After getting a float from an outside source, we want to search the database to return the attribute with the closest number to that float. (ex. for r, if we get a value of 199, the r value with the closest value to 199 will be returned).
I know there are predicates that can be used like: "text CONTAINS[c] %#" but I didn't see any predicates for 'closest value'.
You can use NSSortDescriptor(key: "name_key", ascending: true) with your request.
let request1 = NSFetchRequest<NSFetchRequestResult>() // use correct constructor
let sortDescriptor = NSSortDescriptor(key: "name_key", ascending: true)
let sortDescriptors = [sortDescriptor]
request1.sortDescriptors = sortDescriptors
let predicate1 = NSPredicate(format: "text < %#", value)
request1.predicate = predicate1
// use this request1 to fetch from core data
let request2 = NSFetchRequest<NSFetchRequestResult>() // use correct constructor
request2.sortDescriptors = sortDescriptors
let predicate2 = NSPredicate(format: "text > %#", value)
request2.predicate = predicate2
// use this requst2 to fetch from core data
Then you can use predicate twice:
First time with format text < %# and use last item of the array.
and
Second time with format text > %# and use the first item of the array.
compare the difference of your first and last items from both iterations with your given value and see whose difference is smaller. That will be closest value.
If you don't know how to fetch data from core data you can follow Fetching Objects
Getting started with core data

Using NSPredicate to filter Core Data entities without property equal to any of array property

I have a set of Price in Core Data
price1 = Price.newInManagedObjectContext(self.managedObjectContext!)
price1.price = 1
price1.size = 1
price1.market = market1
price2 = Price.newInManagedObjectContext(self.managedObjectContext!)
price2.price = 2
price2.size = 1
price2.market = market1
price3 = Price.newInManagedObjectContext(self.managedObjectContext!)
price3.price = 3
price3.size = 1
price3.market = market1
self.save()
Then I have an update set
let p1 = PriceUpdate(price: 1, size: 2)
let p2 = PriceUpdate(price: 4, size: 2)
let updates = [p1, p2]
And I want to fetch all Price objects in persistent store that don't have a price equal to any of the updates price. In the example that would be the price2 and price3 as price 2 and 3 are not in updates (1 and 4)
I've tried something like this but I'm not sure.
let request = NSFetchRequest()
request.entity = NSEntityDescription.entityForName("Price", inManagedObjectContext: self.managedObjectContext!)
request.predicate = NSPredicate(format: "%K == %#.%K", "price", updates, "price")
i think your can make one more attribute and insert 0 in your table attribute... and when you update your table than insert 1 in new attribute.. so when you fetched the data from table simple make a query with new attribute having 1 in table ...
You don't provide details of PriceUpdate, but I assume it's a struct or similar. Start by constructing an array holding just the prices:
let updatePrices = updates.map() { $0.price }
Then build a predicate which filters out the Price objects if their price is in the above array:
request.predicate = NSPredicate(format: "NOT %K IN %#", "price", updatePrices)

Setting NSPredicate in Swift CoreData

Am Rewriting my existing objective c code(ios) to swift and now am facing some issues with Coredata NSPredicate in swift as there is some many to one relationships and vice-versa.. am using the following code,
let fetchRequest = NSFetchRequest(entityName: "TUMessage")
let sortSequence = NSSortDescriptor(key: "sequence", ascending: true)
let sortTime = NSSortDescriptor(key: "epoch_time", ascending: true)
var filterPredicate:NSPredicate = NSPredicate(format:"thread == [c] %#",contact.threads.anyObject())
 fetchRequest.predicate = filterPredicate
var sortDescriptor:NSArray = NSArray(objects: sortTime,sortSequence)
fetchRequest.sortDescriptors = sortDescriptor
fetchRequest.fetchBatchSize = 50
return fetchRequest
where "TUMessage" is the table we need to fetch data from, "sequence" for sorting the fetched result, "thread == [c] %#" is a relationship of message table (many to one since each contact have multiple thread) ,
and contact.threads.anyObject() is the predicate which am trying to add.Unfortunately am getting the following error
type anyobject? does not confirm to protocol, CVarArgType
Any help would be appreciated..
Thank you
You need to unwrap it and cast to the specific class
contact.threads.anyObject()! as MYClass

Resources