Использование предиката в 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: …). Это обычный шаблон в Swift.)

Итак, теперь нам просто нужно передать аргументы конструктору. В 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

Вы можете использовать фильтры, доступные в Swift, для фильтрации содержимого из массива вместо использования предиката, как в 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
По какой-то причине у меня не получилось написать это так, однако я сделал let myPredicateString = "name contains [c] (searchText)", а затем сделал var resultPredicate: NSPredicate = NSPredicate (format: myPredicateString)
AppHandwerker

5

Я думаю, что это был бы лучший способ сделать это в Swift:

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

1
Это более идиоматично, если вы фильтруете Sequence, но есть случаи, когда вам понадобится NSPredicate, например, при работе с NSFetchedResultsController.
Jarsen 08

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.