问题
I create a search NSPredicate
using a custom format string. Sometimes the syntax of this string is wrong and when I execute a fetch using a NSFetchRequest
with this predicate I get a NSInvalidArgumentException
, for example when the key-path is incorrect. I would much rather prefer to validate this predicate (call some method that returns YES
if format is ok), than have an exception thrown that crashes my app. What can I do?
To rephrase the inquiry into a simple question:
Can I validate the predicate without potentially crashing the app?
Here is example code in Swift:
let text = "price > 0.1" // ok, no syntax error
let text = "price > 'abc'" // error
let predicate = NSPredicate.init(format: text, argumentArray: [])
let request = NSFetchRequest<Fruit>.init(entityName: "Fruit")
request.predicate = predicate
request.fetchLimit = 1
let fruit = try myContext.fetch(request) as [Fruit] // exception thrown here that crashes app
// sometimes the exception can be caught with an obj-c try/catch
// sometimes it can't be caught, and causes program to terminate
// CAN WE HAVE A SOLUTION THAT NEVER CAUSES A CRASH ?
回答1:
There's no built-in way to validate that a predicate format string is a valid predicate. With format strings, you really need to validate the predicates by (a) testing them during development and (b) verifying that substitution values in predicates are at least the right data type.
If that's a problem, you might find it better to build your predicates in other ways, instead of with format strings. For example, use NSComparisonPredicate
and NSCompoundPredicate
to build the predicates from instances of NSExpression
. The code will be much more verbose, but it will be easier to ensure that your predicate is valid by checking each part of it as you construct it.
回答2:
You can make use of evaluate(with:)
to validate NSPredicate
's format,
Returns a Boolean value indicating whether the specified object matches the conditions specified by the predicate.
Swift 4.2:
For example,
let dataArray = [
"Amazon",
"Flipkart",
"Snapdeal",
"eBay",
"Jabong",
"Myntra",
"Bestbuy",
"Alibaba",
"Shopclue"
]
let searchString = "buy"
let predicate = NSPredicate(format: "SELF contains %@", searchString)
let searchResult = dataArray.filter { predicate.evaluate(with: $0) }
print(searchDataSource)
if !searchResult.isEmpty {
//success
} else {
//evaluation failed
}
To avoid an exception, you may want to use try-catch
block
来源:https://stackoverflow.com/questions/53970414/how-to-validate-nspredicate-before-calling-fetch