NSPredicate substring in string - ios

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.

Related

Predicate with many conditions and one argument

I'm trying to query contacts realm db but I've one query string, do I need to repeat it over in the predicate or there's a better way?
let contactResults = realm.objects(ContactRealm.self).filter("is_Contact == true AND full_name CONTAINS[c] %# OR phone_number_one CONTAINS[c] %# OR phone_number_two CONTAINS[c] %# OR phone_number_three CONTAINS[c] %# OR email_address_one CONTAINS[c] %# OR email_address_two CONTAINS[c] %#", query, query, query, query, query, query).sorted(byKeyPath: "full_name", ascending: true)
also is querying like this considered a bad practice?
update: as suggested by a comment here:
let predicateContact = NSPredicate(format: "is_Contact == true")
let fullname = NSPredicate(format: "full_name CONTAINS[c] %#", query)
let phoneNumber = NSPredicate(format: "phone_number_one CONTAINS[c] %#", query)
let phonenumbertwo = NSPredicate(format: "phone_number_one CONTAINS[c] %#", query)
let email = NSPredicate(format: "phone_number_one CONTAINS[c] %#", query)
let secondEmail = NSPredicate(format: "phone_number_one CONTAINS[c] %#", query)
let compoundOr = NSCompoundPredicate(orPredicateWithSubpredicates: [fullname, phoneNumber, phonenumbertwo, email, secondEmail])
let compound = NSCompoundPredicate(type: .and, subpredicates: [predicateContact, compoundOr])
let contactResults = realm.objects(ContactRealm.self).filter(compound).sorted(byKeyPath: "full_name", ascending: true)
Since your predicates look the same and only show a difference in the name of the attribute, I would suggest to create an array of attribute names. Then, you can create an NSPredicate for each name by looping through the names.
let attributes = ["full_name", "phone_number_one", "phone_number_two", "phone_number_three", "email_address_one", "email_address_two"]
let contactPredicateArray = parameters.map {
NSPredicate("\($0) CONTAINS[c] %#", query)
}
let contactPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: contactPredicateArray)
let isContactPredicte = NSPredicate(format: "is_Contact == %#", true)
let predicate = NSCompoundPredicate(type: .and, subpredicates: [isContactPredicte, contactPredicate])
This way, the code is more flexible because removing or adding single attributes to your predicate can be done very easily by modifying the attributes array. It is also more readable because all attributes are defined in one line and not all over the place.

How to pass the same parameter multiple times in CoreData iOS predicate builder?

I have a UITableView with a UISearchbar that let me filter the data based on the search text from the UISearchbar.
The CoreData table contains 3 attributes
name, notes, date
I want to search the three columns for any occurrence based on the User search text.
So I tried this on:
let searchText = searchText.lowercased()
let query = "name contains[cd] %# OR notes contains[cd] %# OR date contains[cd] %#"
let predicate = NSPredicate(format: query, searchText, searchText, searchText)
Is there any way to pass the same parameter (searchText) one time?
Something like Java string formatter:
let query = "name contains[cd] %1$# OR notes contains[cd] %1$# OR date contains[cd] %1$#"
let predicate = NSPredicate(format: query, searchText)
You can use substitution variables:
let searchText = searchText.lowercased()
let template = NSPredicate(format: "name contains[cd] $SRCH OR notes contains[cd] $SRCH OR date contains[cd] $SRCH")
let subVars = ["SRCH": searchText]
let predicate = template.withSubstitutionVariables(subVars)
See "Creating Predicates using Predicate Templates" in the Apple Documentation.

Core data Fetch request error for predicate

Need
I have to find the record with rec_name is "Apple 256GB Macbook" & isActive == true.
Fetch Request
fetchRequest.predicate = NSPredicate(format: "rec_name LIKE[cd] *%#* AND rec_name LIKE[cd] *%#* AND isActive = %#","apple","macbook",true)
Error
Unable to parse the format string "rec_name LIKE[cd] *%#* AND rec_name LIKE[cd] *%#* AND isActive = %#"
Thank you,
The problem is because of *%#* here %# between the * is not replaced by a string argument so NSPredicate is not able to make your query LIKE *apple* and LIKE *macbook* what you need to do is make a search string with wildcards and with Like simply use %#, also as #Vadian suggested use number instead of Bool.
let searchkeyword1 = "apple"
let searchkeyword2 = "macbook"
//Make search string wildcards charaters
let searchString1 = "*\(searchkeyword1)*"
let searchString2 = "*\(searchkeyword2)*"
fetchRequest.predicate = NSPredicate(format: "rec_name LIKE[cd] %# AND rec_name LIKE[cd] %# AND isActive = %#", searchString1,searchString2, true as NSNumber)
Also batter option here is you can use CONTAINS and no need to use of wildcards.
fetchRequest.predicate = NSPredicate(format: "rec_name CONTAINS[cd] %# AND rec_name CONTAINS[cd] %# AND isActive = %#", "apple","macbook", true as NSNumber)
You can do one more thing if you want to find all record start with apple and end with macbook then you can simply use BEGINSWITH and ENDSWITH
fetchRequest.predicate = NSPredicate(format: "rec_name BEGINSWITH[cd] %# AND rec_name ENDSWITH[cd] %# AND isActive = %#", "apple","macbook", true as NSNumber)
Try this
fetchRequest.predicate = NSPredicate(format: "rec_name LIKE[cd] %# AND rec_name LIKE[cd] %# AND isActive = %#","apple","macbook",NSNumber(booleanLiteral: true))
You need to set a predicate query like following:
fetchRequest.predicate = NSPredicate(format: "rec_name == %# AND isActive == %#" , "Apple 256GB Macbook", NSNumber(booleanLiteral: true))
I don't think we need to use Like if you are looking for perfect match.
Try this
NSPredicate(format: "rec_name == %# AND rec_name == %# AND isActive = %d","apple","macbook",true)

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] %#", ...)

Resources