Używanie predykatu w Swift


94

Pracuję tutaj nad samouczkiem (uczę się języka Swift) dla mojej pierwszej aplikacji: http://www.appcoda.com/search-bar-tutorial-ios7/

Utknąłem w tej części (kod Objective-C):

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
    NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"name contains[c]         %@", searchText];
    searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}

Czy ktoś może doradzić, jak stworzyć odpowiednik dla NSPredicate w Swift?

Odpowiedzi:


158

To naprawdę jest tylko przełącznik składni. OK, mamy więc wywołanie metody:

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

W Swift konstruktory pomijają część „blahWith…” i po prostu używają nazwy klasy jako funkcji, a następnie przechodzą bezpośrednio do argumentów, tak [NSPredicate predicateWithFormat: …]by się stało NSPredicate(format: …). (Na innym przykładzie [NSArray arrayWithObject: …]będzie to NSArray(object: …). Jest to normalny wzorzec w języku Swift).

Więc teraz musimy tylko przekazać argumenty do konstruktora. W Objective-C literały NSString wyglądają jak @"", ale w Swift używamy po prostu cudzysłowów dla łańcuchów. To daje nam:

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

I faktycznie tego właśnie tutaj potrzebujemy.

(Nawiasem mówiąc, zauważysz, że niektóre inne odpowiedzi zamiast tego używają ciągu formatu, takiego jak "name contains[c] \(searchText)". To nie jest poprawne. To używa interpolacji ciągów, która różni się od formatowania predykatów i generalnie nie działa w tym przypadku).


Dzięki. Uratujesz mnie pewnego dnia!
Hugo,

2
Aby odnieść się do drugiej linii metody, możesz użyć predykatu jako:searchResults = recipes.filter { resultPredicate.evaluateWithObject($0) }
Ben Packard

44

Pracuję z predykatem przez dość długi czas. Oto mój wniosek (SWIFT)

//Customizable! (for me was just important if at least one)
request.fetchLimit = 1


//IF IS EQUAL

//1 OBJECT
request.predicate = NSPredicate(format: "name = %@", txtFieldName.text)

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


// IF CONTAINS

//1 OBJECT
request.predicate = NSPredicate(format: "name contains[c] %@", txtFieldName.text)

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

1
Co jest równe LIKE 'a%z'?
TomSawyer

@ Jiří Zahálka Co to jest prośba o wysłuchanie?
Muju

28

Przykład użycia w Swift 2.0

let dataSource = [
    "Domain CheckService",
    "IMEI check",
    "Compliant about service provider",
    "Compliant about TRA",
    "Enquires",
    "Suggestion",
    "SMS Spam",
    "Poor Coverage",
    "Help Salim"
]
let searchString = "Enq"
let predicate = NSPredicate(format: "SELF contains %@", searchString)
let searchDataSource = dataSource.filter { predicate.evaluateWithObject($0) }

Otrzymasz (plac zabaw)

wprowadź opis obrazu tutaj


A co, jeśli ... Jeśli mam szereg słowników? Jak mogę przeanalizować, aby uzyskać dane?
Revathy Durairajan

1
@RevathyDurairajan potrzebujesz SELF.yourkeyname do filtrowania tablicy słowników.
Pawan Rai

11

Możesz użyć filtrów dostępnych w swift, aby odfiltrować zawartość z tablicy zamiast używać predykatu, takiego jak w Objective-C.

Przykład w Swift 4.0 jest następujący:

var stringArray = ["foundation","coredata","coregraphics"]
stringArray = stringArray.filter { $0.contains("core") }

W powyższym przykładzie, ponieważ każdy element tablicy jest łańcuchem, możesz użyć containsmetody do filtrowania tablicy.

Jeśli tablica zawiera obiekty niestandardowe, właściwości tego obiektu można wykorzystać do podobnego filtrowania elementów.


5

Użyj poniższego kodu:

 func filterContentForSearchText(searchText:NSString, scopes scope:NSString)
{
    //var searchText = ""

    var resultPredicate : NSPredicate = NSPredicate(format: "name contains[c]\(searchText)", nil)

    //var recipes : NSArray = NSArray()

    var searchResults = recipes.filteredArrayUsingPredicate(resultPredicate)
}

1
Z jakiegoś powodu pisanie tego w ten sposób nie zadziałało, ale zrobienie tego, aby myPredicateString = "name zawiera [c] (searchText)", a następnie zrobienie var resultPredicate: NSPredicate = NSPredicate (format: myPredicateString)
działało

5

Myślę, że byłby to lepszy sposób na zrobienie tego w Swift:

func filterContentForSearchText(searchText:NSString, scope:NSString)
{
   searchResults = recipes.filter { name.rangeOfString(searchText) != nil  }
}

1
Jest to bardziej idiomatyczne, jeśli filtrujesz a Sequence, ale są przypadki, w których będziesz potrzebować a NSPredicate, np NSFetchedResultsController.
Jarsen,

1

W szybkim 2.2

func filterContentForSearchText(searchText: String, scope: String) {
    var resultPredicate = NSPredicate(format: "name contains[c]         %@", searchText)
    searchResults = (recipes as NSArray).filteredArrayUsingPredicate(resultPredicate)
}

W Swift 3.0

func filterContent(forSearchText searchText: String, scope: String) {
        var resultPredicate = NSPredicate(format: "name contains[c]         %@", searchText)
        searchResults = recipes.filtered(using: resultPredicate)
    }

1

// zmień "nazwę" i "wartość" zgodnie z danymi twojej tablicy.

// Zmień nazwę "yourDataArrayName" zgodnie z twoją tablicą (NSArray).

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

    if let sortedDta = yourDataArrayName.filtered(using: resultPredicate) as? NSArray {

 //enter code here.

        print(sortedDta)
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.