Сравнить целое число со строкой в NSPredicate
У меня есть в проекте множество программ тренировок (код для них находится на Objective-C) и в каждой программе, которая у меня есть @property (nullable, nonatomic, copy) NSString *scheduleStr;для продолжительности программы. Это свойство хранит такие значения, как 1 неделя , 2 недели , 3 недели и т. Д. Мне нужно отфильтровать все значения, превышающие 6 недель. Я пытаюсь применить NSPredicate:
predicates.append(NSPredicate(format: "scheduleStr.integerValue >= 6"))
и после этого я получаю только программы продолжительностью 6-9 недель, но не более 10 недель, но наверняка у меня в базе есть несколько программ продолжительностью 12 недель. Если я пытаюсь применить что-то вроде этого:
predicates.append(NSPredicate(format: "scheduleStr.integerValue >= 10"))
Я получу почти все программы. Как получить все программы с более чем выбранными значениями?
Ответы
Проблема в том, что, хотя вы и указываете integerValue, при использовании предиката как части выборки CoreData обрабатывает вашу строку как строку. В строковом выражении 10 weeksэто «меньше чем» 6 weeks, поэтому оно исключается из результатов.
Вы должны сохранить число (как Int) вместо сохранения строки. Добавление текста «недели» - это то, что вы делаете для отображения. Если вы храните число, а не строку, CoreData может выполнять численное сравнение, и ваш предикат будет работать так, как вы ожидаете.
Если вы действительно не хотите этого делать, есть один обходной путь и один взлом. Обходной путь - фильтровать объекты в памяти, а не как часть выборки. Тогда integerValueбудет правильно интерпретировано, и сравнение будет числовым.
Хакерство заключается в том, чтобы заставить CoreData обрабатывать вашу строку, как будто это число, с помощью числовой функции, например abs(при условии, что у вас есть только положительное количество недель, взятие абсолютного значения оставляет значение без изменений):
predicates.append(NSPredicate(format: "abs:(scheduleStr) >= 6"))
Чтобы получить целую часть в строке в вашем случае, вы можете посмотреть что-то вроде:
Предположим, что element - это ваша строка, тогда
let component = element.components(separatedBy: .letters) // this will give you the non letter values
let integerValues = component.filter({ $0 != "" })
print(integerValues[0]) // As first value in your input string is an integer
Это даст вам целую часть строки, которую можно использовать для фильтрации массива.