Получение ошибки компилятора при попытке написать сложный предикат

Я знаю, что существуют подобные вопросы, например, этот Объединение предикатов в 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.

Заголовок вопроса состоит из двух названий фреймворков и одного имени макроса и ничего больше. Пожалуйста, постарайтесь написать правильное название

Joakim Danielson 04.05.2024 16:43

Одним из возможных улучшений является развертывание dateStart с помощью if let

Joakim Danielson 04.05.2024 16:52

@MojtabaHosseini добавил ссылку в описание.

grep 07.05.2024 19:56
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
177
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема

Это потому, что вы сравниваете 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.

grep 07.05.2024 20:45

К сожалению, метод 1 невозможен, так как допустимо иметь нулевое значение. Не могли бы вы подробнее рассказать о методе 2, не знаю, как его реализовать @MojtabaHosseini

grep 08.05.2024 06:18

Вы можете просто скопировать этот код в файл, чтобы исходный код скомпилировался. Потому что это делает типы Date? сопоставимыми. @grep

Mojtaba Hosseini 08.05.2024 09:09

Должен признаться, я не понимаю этот фрагмент кода, но он работает. Отмечаем ваш ответ как принятый. Спасибо. Однако, если попытаться добавить еще одно условие, например проверку на необязательный Bool $0.isActive == true, я снова получу ту же ошибку, есть ли шанс, что вы тоже можете помочь с этим?

grep 08.05.2024 20:59

В качестве краткого описания говорится: сделайте anything, вы МОЖЕТЕ сравнивать изначально, comparable если они представлены как необязательные, но НЕ nil. Я надеюсь, что это помогает.

Mojtaba Hosseini 08.05.2024 21:25

А что касается $0.isActive == true, то с ним не должно быть проблем. Кажется, есть еще одна проблема с кодом. Я обновил пример кода на git, чтобы он содержал Bool?, но если вы его не поняли, попробуйте задать новый вопрос с более подробным описанием и дайте ссылку на него здесь, чтобы я мог посмотреть.

Mojtaba Hosseini 08.05.2024 21:34

@MojtabaHosseini опубликовал новый вопрос. Спасибо. stackoverflow.com/questions/78450900/…

grep 08.05.2024 21:57

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