Поддерживает ли макрос #Predicate в Foundation/SwiftData поиск без учета регистра?

Я тестирую новую платформу SwifData и работаю с новым макросом #Predicate и понял, что он не поддерживает поиск без учета регистра. Макрос не работает с методом lowcased() или свойством localizedLowercase, поэтому, похоже, нет способа создать предикат, нечувствительный к регистру, как мы привыкли делать с NSPredicate и атрибутом [c].

         var predicate = #Predicate<Book> {
  $0.title.localized().contains(search) }

Ошибка: функция нижнего регистра() не поддерживается в этом предикате (из макроса «Предикат»).

Интересно, есть ли какой-нибудь обходной путь? Спасибо

2 ответа

НовыйPredicateмакрос очень хорошо работает сlocalizedStandardContains(_:)функция.

С сайта документации разработчиков Apple :

Это наиболее подходящий метод для поиска строк на уровне пользователя, аналогичный тому, как поиск обычно выполняется в системе. Поиск осуществляется с учетом локали, нечувствителен к регистру и диакритическим знакам. Точный список примененных параметров поиска может со временем измениться.

Использование:

      let userInput = "foo bar"
let predicate = #Predicate<Book> { $0.title.localizedStandardContains(userInput) }

ОБНОВЛЕНИЕ Как отметила Микико Джейн, это работает только в предикате фильтра для массива, а не в@Queryнапрямую.

Я попытался использовать@Transientполе, чтобы на лету сделать его строчными буквами

      @Transient
var nameNormalized: String {
    name.lowercased()
}

Предикат не смог увидеть свойство transient, поскольку я предполагаю, что он ищет только те объекты, которые сохранились в базе данных.

Я полагаю, что единственное решение на данный момент — создать поле, которое обновляется всякий раз, когда обновляется первое поле. Это слишком много накладных расходов и шаблонов, чтобы просто иметь правильную функциональность поиска. Кажется, это явно противоречит целям SwiftData.

Оригинальный ответ


Я поигрался с этим, перепробовав множество решений, но, возможно, нашел способ выполнить сравнение без учета регистра. В примере проекта SwiftData SampleTrips я изменил

      let filteredList = try? trip.bucketList.filter(#Predicate { item in
    item.title.contains(searchText) && tripName == item.trip?.name
})

к:

      let filteredList = try? trip.bucketList.filter(#Predicate { item in
    return item.title.localizedLowercase.contains(searchText.localizedLowercase) && tripName == item.trip?.name
})

Кажется, это сработало. Кажется, макрос поддерживаетlocalizedLowercaseно не дляlowerCased()

Другие вопросы по тегам