Використання предиката в Swift


93

Я працюю з підручником тут (вивчаю Swift) для свого першого додатка: http://www.appcoda.com/search-bar-tutorial-ios7/

Я застряг у цій частині (код Objective-C):

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

Хтось може порадити, як створити еквівалент для NSPredicate в Swift?

Відповіді:


158

Це насправді просто перемикач синтаксису. Добре, отже, ми маємо виклик цього методу:

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

У Swift конструктори пропускають частину "blahWith ..." і просто використовують ім'я класу як функцію, а потім переходять безпосередньо до аргументів, [NSPredicate predicateWithFormat: …]що стане NSPredicate(format: …). (Для іншого прикладу [NSArray arrayWithObject: …]стало б NSArray(object: …). Це звичайний зразок у Свіфта.)

Отже, нам просто потрібно передати аргументи конструктору. У Objective-C виглядають літерали NSString @"", але в Swift ми просто використовуємо лапки для рядків. Отже, це дає нам:

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

І насправді саме тут нам потрібно.

(До речі, ви помітите, що деякі інші відповіді замість цього використовують рядок форматування, наприклад "name contains[c] \(searchText)". Це неправильно. Тут використовується інтерполяція рядків, яка відрізняється від форматування предикатів і, як правило, не працює для цього.)


Дякую. Ти врятуєш мене одного дня!
Гюго

2
Щоб звернутися до другого рядка вашого методу, ви можете використовувати присудок як:searchResults = recipes.filter { resultPredicate.evaluateWithObject($0) }
Бен Пакард

43

Робота з присудком досить тривалий час. Ось мій висновок (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
Що рівне з LIKE 'a%z'?
TomSawyer

@ Jiří Zahálka Що означає запит почути?
Муджу

28

Приклад використання в 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) }

Ви отримаєте (дитячий майданчик)

введіть тут опис зображення


Що якщо ... Якщо у мене є безліч словників? Як зробити аналіз, щоб отримати дані?
Revathy Durairajan,

1
@RevathyDurairajan вам потрібно SELF.yourkeyname для фільтрації масиву словників.
Pawan Rai

11

Ви можете використовувати фільтри, доступні у швидкому режимі, для фільтрування вмісту з масиву замість використання предиката, як у Objective-C.

Приклад у Swift 4.0:

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

У наведеному вище прикладі, оскільки кожен елемент масиву є рядком, ви можете використовувати containsметод фільтрації масиву.

Якщо масив містить власні об'єкти, то властивості цього об’єкта можна використовувати для фільтрації елементів аналогічно.


6

Використовуйте код нижче:

 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
З якоїсь причини таке написання мені не вдалося, однак дозвольте myPredicateString = "ім'я містить [c] (searchText)", а потім виконайте var resultPredicate: NSPredicate = NSPredicate (формат: myPredicateString) did
AppHandwerker

5

Я думаю, що це було б кращим способом зробити це в Swift:

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

1
Це більш ідіоматично, якщо ви фільтруєте a Sequence, але бувають випадки, коли вам знадобиться NSPredicate, наприклад, коли ви маєте справу NSFetchedResultsController.
Ярсен

1

Швидко 2.2

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

У швидкій версії 3.0

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

1

// змінити "ім'я" та "значення" відповідно до даних масиву.

// Змініть ім'я "yourDataArrayName", що відповідає вашому масиву (NSArray).

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

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

 //enter code here.

        print(sortedDta)
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.