Я знаю, что существуют подобные вопросы, например, этот Объединение предикатов в SwiftData, но все это кажется мне ненужным сложным, и мне трудно поверить, что нет более простого способа.
Это то, что мне нужно:
let aPred = #Predicate<Event> {
$0.dateStart != nil &&
($0.dateStart >= startOfDay && $0.dateStart <= endOfDay) ||
($0.dateEnd >= startOfDay && $0.dateEnd <= endOfDay) ||
($0.dateStart < startOfDay && $0.dateEnd >= startOfDay)
}
Event
— это модель SwiftData, которая имеет 2 необязательных свойства даты dateStart
и dateEnd
, которые мне нужно сравнить с двумя датами startOfDay
и endOfDay
Вы, вероятно, знаете, что это приведет к ошибке компиляции:
Компилятор не может проверить тип этого выражения в разумные сроки; попробуйте разбить выражение на отдельные подвыражения.
В Core Data мы могли бы легко сделать это с помощью одного NSPredicate, например:
let nsPred = NSPredicate(format: "dateStart != nil && (dateStart >= %@ && dateStart <= %@) || (dateEnd >= %@ && dateEnd <= %@) || (dateStart < %@ && dateEnd >= %@)",
argumentArray: [startOfDay, endOfDay,
startOfDay, endOfDay,
startOfDay, startOfDay])
Или, если необходимо, мы могли бы разбить это на более мелкие предикаты, а затем использовать NSCompoundPredicate
с .and or .or
.
Должен быть простой способ добиться того же в SwiftData без всех этих сложных макросов, запросов и выражений предикатов.
Мне приходится оставлять каждый элемент необязательным, поскольку этого требует CloudKit.
Загрузил минимальный рабочий проект сюда. См. ViewController.swift.
Одним из возможных улучшений является развертывание dateStart с помощью if let
@MojtabaHosseini добавил ссылку в описание.
Это потому, что вы сравниваете Optional<Date>
с Date
.
Попробуйте избавиться от необязательности каким-то образом, например, расширив Optional
, чтобы можно было сравнить:
extension Optional: Comparable where Wrapped: Comparable {
public static func < (lhs: Wrapped?, rhs: Wrapped?) -> Bool {
guard let lhs, let rhs else { return false }
return lhs < rhs
}
}
👉 Here is a working demo with optional predicate 👈
Мне приходится оставлять каждый элемент необязательным, поскольку этого требует CloudKit.
К сожалению, метод 1 невозможен, так как допустимо иметь нулевое значение. Не могли бы вы подробнее рассказать о методе 2, не знаю, как его реализовать @MojtabaHosseini
Вы можете просто скопировать этот код в файл, чтобы исходный код скомпилировался. Потому что это делает типы Date?
сопоставимыми. @grep
Должен признаться, я не понимаю этот фрагмент кода, но он работает. Отмечаем ваш ответ как принятый. Спасибо. Однако, если попытаться добавить еще одно условие, например проверку на необязательный Bool $0.isActive == true, я снова получу ту же ошибку, есть ли шанс, что вы тоже можете помочь с этим?
В качестве краткого описания говорится: сделайте anything
, вы МОЖЕТЕ сравнивать изначально, comparable
если они представлены как необязательные, но НЕ nil
. Я надеюсь, что это помогает.
А что касается $0.isActive == true
, то с ним не должно быть проблем. Кажется, есть еще одна проблема с кодом. Я обновил пример кода на git, чтобы он содержал Bool?
, но если вы его не поняли, попробуйте задать новый вопрос с более подробным описанием и дайте ссылку на него здесь, чтобы я мог посмотреть.
@MojtabaHosseini опубликовал новый вопрос. Спасибо. stackoverflow.com/questions/78450900/…
Заголовок вопроса состоит из двух названий фреймворков и одного имени макроса и ничего больше. Пожалуйста, постарайтесь написать правильное название