Using Predicate in Swift

Using Predicate in Swift

This is really just a syntax switch. OK, so we have this method call:

[NSPredicate predicateWithFormat:@"name contains[c] %@", searchText];

In Swift, constructors skip the "blahWith…" part and just use the class name as a function and then go straight to the arguments, so [NSPredicate predicateWithFormat: …] would become NSPredicate(format: …). (For another example, [NSArray arrayWithObject: …] would become NSArray(object: …). This is a regular pattern in Swift.)

So now we just need to pass the arguments to the constructor. In Objective-C, NSString literals look like @"", but in Swift we just use quotation marks for strings. So that gives us:

let resultPredicate = NSPredicate(format: "name contains[c] %@", searchText)

And in fact that is exactly what we need here.

(Incidentally, you'll notice some of the other answers instead use a format string like "name contains[c] \(searchText)". That is not correct. That uses string interpolation, which is different from predicate formatting and will generally not work for this.)

How to use predicates in swift?

You can use any Objective C apis in swift.

 var resultPredicate = NSPredicate(format: "name contains[c]%@",searchText)
filteredArray = arrayToFIlter.filtered(using: resultPredicate)

1) NSPredicate(format: "name = %@", demoText)

//ARRAY
2) NSPredicate(format: "name = %@ AND nickName = %@", argumentArray: [name, nickname])

// IF CONTAINS
3)NSPredicate(format: "name contains[c] %@", demoText)

//ARRAY
4) NSPredicate(format: "name contains[c] %@ AND nickName contains[c] %@", argumentArray: [name, nickname])

Well try array filter: method as well

let digits = [1,4,10,15]
let even = digits.filter { $0 % 2 == 0 }
// [4, 10]

Its quite intuitive and less code after all, more swifty type.

YOUR QUERY:

//salary greater than 2000
a)let filteredArray = arrayDemo.filter({(($0["epmloyement"] as! Dictionary<String,Any>)["salary"] as! Int) > 2000})

//group = A and salary > 2000
b)let fa = arrayDemo.filter({(($0["epmloyement"] as! Dictionary<String,Any>)["salary"] as! Int) > 2000 && ($0["group"] as! String) == "A"})

Swift Predicate AND and OR in one

You need two NSCompoundPredicate.

let predicate1 = NSPredicate(format: "id contains[cd] %@", searchedText)
let predicate2 = NSPredicate(format: "name contains[cd] %@", searchedText)
let predicate3 = NSPredicate(format: "threadManu = %@", manu)

let predicateOr = NSCompoundPredicate(type: .or, subpredicates: [predicate1, predicate2])
let predicate = NSCompoundPredicate(type: .and, subpredicates: [predicateOr, predicate3])

Swift 4: NSPredicate from UITextField and array of custom object

I think for this to properly work, you need to make your object available to the Objective-C side:

class MyObject: NSObject {
init(code: String, name: String) {
self.code = code
self.name = name
}

var code: String
@objc var name: String
}

The predicate is evaluated over the object you give it. In your case, you provide it a String. For the predicate to check that, you should use self:

let resultPredicate = NSPredicate(format: "self contains[cd] %@", searchText)

let filtered = allDatasource.filter {
resultPredicate.evaluate(with: $0.name)
}

You can also give it a MyObject to evaluate, then you can use the name of the property:

let resultPredicate = NSPredicate(format: "name contains[cd] %@", searchText)

let filtered = allDatasource.filter {
resultPredicate.evaluate(with: $0)
}

In your code, you use the ANY modifier. That's a modifier you can use to check if there is any item in a collection that adheres to the predicate:

let searchText = "n2"
let resultPredicate = NSPredicate(format: "ANY name contains[cd] %@", searchText)

let allDatasource = [ MyObject(code: "c1", name: "n1"), MyObject(code: "c2", name: "n2")]
let containsAnyObject = resultPredicate.evaluate(with: allDatasource)

// true for 'n2'

How to filter an array using NSPredicate in swift 3

The native Swift equivalent to the ObjC code is

let filteredArray = arrayDirectory.filter { ($0["displayName2"] as! String).range(of: searchText!, options: [.diacriticInsensitive, .caseInsensitive]) != nil }

assuming arrayDirectory is a native Swift Array. It considers also the case insensitive and diacritic insensitive parameters.

Swift: Using Extensions in NSPredicate

"Could I do the following"

No. NSPredicate comes with its own completely specified language. Predicate strings must conform to that language; otherwise, they cannot be parsed.

"If not, what is an alternative?"

An alternative to do what? You are not telling us anything about the goal here. For example, instead of calling NSPredicate(format:), you might be able to call NSPredicate(block:) which lets you write the predicate test in Swift code. But you can't do that in all situations. And you have not said what your situation is.

How to combine 2 CoreData predicates in Swift?

If I understand it correctly:

  • There is a one-to-many relationship from Garage to Car,
  • there is a many-to-many relationship from Category to Car,

and you want to count all cars which

  • belong to one of the given garages (which should be active), and
  • have at least one category of the given set of categories.

The first request can be done with

let p1 = NSPredicate(format: "carInGarage.active = TRUE AND carInGarage IN %@", garages)

and the second with

let p2 = NSPredicate(format: "ANY carHasCategories IN %@", categories)

and the combination with

let p = NSCompoundPredicate(andPredicateWithSubpredicates: [p1, p2])

It might be that “ANY IN” does not work with many-to-many relationships,
in that case

let p2 = NSPredicate(format: "SUBQUERY(carHasCategories,$c,$c IN %@").@count > 0, categories)

should do the job.



Related Topics



Leave a reply



Submit