can´t understand fetchRequest.predicate - ios

I´ve a quite "simple" predicate for a NSFetchRequest:
guard let kategorie = self.fetchedResultsController.objectAtIndexPath(indexPath) as? Kategorien else {
return
}
let fetchRequest = NSFetchRequest(entityName: "Details")
fetchRequest.predicate = NSPredicate(format: "kategorie == %i", kategorie.katid!)
do {
let results = try self.managedObjectContext.executeFetchRequest(fetchRequest) as! [Details]
...
The content of the sqllite-"table" is
the content of the variables are
So from
fetchRequest.predicate = NSPredicate(format: "kategorie == %i", kategorie.katid!)
i get the Predicate
kategorie == 18
while
kategorie.katid is 1
I can´t understand it :-(
Any help???

That's really strange, but you can just do:
NSPredicate(format: "kategorie = \(kategorie.katid!)")
And then you don't need to worry about whether you need a %i, or a %ld, or a %#, etc...

katid is an (optional) NSNumber, and what happens in your case
is that the (lower 32-bit of the) address of the object is taken as an integer.
The correct format
specifier is %# (for instances of NSObject subclasses):
NSPredicate(format: "kategorie == %#", kategorie.katid!)
Alternatively, convert the object to an integer:
NSPredicate(format: "kategorie == %d", kategorie.katid!.intValue)
Of course, forced unwrapping should be avoided, e.g.
NSPredicate(format: "kategorie == %d", kategorie.katid?.intValue ?? 0)
Using string interpolation in the format string (as suggested by
#Gargoyle) is another solution in this special case of numbers,
but not generally: If you interpolate a string then any percent
character will be interpreted as a format specifier and that leads
to unexpected output or crashes. Also single or double quotes will
lead to problems because these have a special meaning in predicate
format strings.

Related

NSPredicate crash after swift 3 migration

after migration to swift3, I have an issue that cannot fix
let fetchRequest: NSFetchRequest<User> = User.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "id == %#", id)
my App crashes on second line, bad access, no reason. types are right, no log, nothing, just bad access. any suggestions?
Found a reason, predicate is wrong, cause id is Int64 type, have no idea what kind of predicate I need for this version of swift
The %# format expect a Foundation object as argument, compare
"Predicate Format String Syntax" in the "Predicate Programming Guide".
You can bridge the Int64 to NSNumber:
let id = Int64.max
let predicate = NSPredicate(format: "id == %#", id as NSNumber)
print(predicate) // id == 9223372036854775807
or change the format to "long long":
let id = Int64.max
let predicate = NSPredicate(format: "id == %lld", id)
print(predicate) // id == 9223372036854775807
Bridging all number types to NSNumber is possible as of Swift 3.0.1 (Xcode 8.1) with the implementation of
SE-0139 Bridge Numeric Types to NSNumber and Cocoa Structs to NSValue.

NSPredicate use array as filter

I'm trying to use an array as a filter to search Core Data. The values that the fetchRequest returns should have an ID that is in the predicate's array.
let arrayOfFavoriteStampIDS = [302,2300,2309]
fetchRequest.predicate = NSPredicate(format: "itemID IN %i", argumentArray: arrayOfFavoriteStampIDS)
Almost
fetchRequest.predicate = NSPredicate(format: "itemID IN %#", arrayOfFavoriteStampIDS)
argumentArray means something else for example
fetchRequest.predicate = NSPredicate(format: "itemID == %i OR itemID == %i OR itemID == %i", argumentArray:arrayOfFavoriteStampIDS)
In this case each item in the array must match one %i placeholder.

NSPredicate Exact Match with String

hello I am working on swift. I need to know how can I find results which matches the exact string. Here's my code
let userID: String = String(sender.tag)
// Create a Predicate with mapping to trip_id
let filterByRequest: NSPredicate = NSPredicate(format: "%K.%K CONTAINS[c] %#", "ProductRequest", "user_id", userID)
// Filter your main array with predicate, resulting array will have filtered objects
let filteredArray: [AnyObject] = self.array.filteredArrayUsingPredicate(filterByRequest)
The problem is If user id is 69 it shows results of users whose id is 69, 6, and 9.
I googled but I find some answers closed to my question but they were all in objective C.
Use MATCHES in predicate as following :
let filterByRequest: NSPredicate = NSPredicate(format: "%K.%K MATCHES %#", "ProductRequest", "user_id", userID)
Hope it helps..
To test for exact equality, simply use == instead of CONTAINS:
NSPredicate(format: "%K.%K == %#", ...)
This can also be combined with [c] for case-insensitive equality:
NSPredicate(format: "%K.%K ==[c] %#", ...)

NSPredicate with multiple arguments and "AND behaviour"

I have a function which fetches those objects from a particular entity that fulfill a specified criterion:
func fetchWithPredicate(entityName: String, argumentArray: [AnyObject]) -> [NSManagedObject] {
let fetchRequest = NSFetchRequest(entityName: entityName)
fetchRequest.predicate = NSPredicate(format: "%K == %#", argumentArray: argumentArray)
do {
return try self.managedContext.executeFetchRequest(fetchRequest) as! [NSManagedObject]
} catch {
let fetchError = error as NSError
print(fetchError)
return [NSManagedObject]()
}
}
When I pass an array with multiple aguments (multiple attribute names and values) it seems that creates a query like this:
attributeName1 = value1 OR attributeName2 = value2 OR attributeName3 = value3 OR...
I would like to change these ORs for ANDs.
EDIT:
The problem was that it was only replacing the first two items with "%K == %#".
So, I have to create a NSCompoundPredicate to create a predicate dynamically.
In your example the %K and %# format tokens are replaced only by the first two items of the argument array, the other items are ignored.
You have to provide all format tokens to be replaced in the string for example
NSPredicate(format: "%K == %# AND %K == %#", argumentArray:["key1", "value1", "key2", "value2"])
To create a predicate (with a variable number of expressions) dynamically, use NSCompoundPredicate, e.g.
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: subPredicates)
where subPredicates is a [NSPredicate] array, and each subpredicate
is created from the provided arguments in a loop with
NSPredicate(format: "%K == %#", key, value)
Something like this (untested):
func fetchWithPredicate(entityName: String, argumentArray: [NSObject]) -> [NSManagedObject] {
var subPredicates : [NSPredicate] = []
for i in 0.stride(to: argumentArray.count, by: 2) {
let key = argumentArray[i]
let value = argumentArray[i+1]
let subPredicate = NSPredicate(format: "%K == %#", key, value)
subPredicates.append(subPredicate)
}
let fetchRequest = NSFetchRequest(entityName: entityName)
fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: subPredicates)
// ...
}
Swift 3
I found easiest way.
var predicate = NSPredicate(format: "key1 = %# AND key2 = %#", value1, value2)
You could use a compound predicate. I'll give you the Objective-C syntax, I'll leave the translation to Swift as an exercise...
If your keys and values are in a dictionary:
NSDictionary *conds = #{ #"key1": #"value1", #"key2", #"value2" };
NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:conds.allKeys.length];
for (NSString *key in conds.allKeys)
{
[predicates addObject:[NSPredicate predicateWithFormat:#"%K == %#", key, conds[key]]];
}
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];
Swift 5
let predicate = NSPredicate(format: "id = %# AND title = %#", argumentArray: ["id value", "title value"])

NSPredicate substring in string

I want to show all items where value1 contains value2. I tried this:
let fetchRequest = NSFetchRequest(entityName: "Product")
fetchRequest.predicate = NSPredicate(format: "value1 CONTAINS[cd] value2")
value1, value2 - current object values, it is not variables
But i got error:
Unable to parse the format string
Why it doesn't allow me to do this ?
Try to use this predicate:
let predicate = NSPredicate(format: "value1 CONTAINS[cd] %#", value2)
As were investigated during communication with developer. Issue is in data that is saved to the database. In his case data is saved with quotes ("") and NSPredicate(format: "value1 CONTAINS[cd] %#", value2) is working with errors due to that issue.

Resources