How to validate NSPredicate before calling fetch

纵饮孤独 提交于 2020-06-29 06:13:39

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!