Преобразование выражения фильтра в формат NSPredicate

#swift #realm #nspredicate

#swift #область #nspredicate

Вопрос:

Я хотел бы выполнить этот метод фильтрации с использованием NSPredicate, но у меня возникли проблемы с преобразованием синтаксиса.

 objectsCollection.filter { $0.stringIds.contains(id) }
 

Пример класса

 class Object {
    let stringIds: [String]
}

let objectsCollection: [Object]
let id = "The id we want to look for"
objectsCollection.filter { $0.stringIds.contains(id) }
 

Моя попытка с NSPredicate

Вот как я думал, что это будет работать, но, похоже, это не так.

 let filter = NSPredicate(format: "%@ IN stringIds", id)
objectsCollection.filter(filter)
 

Ошибка

 reason: 'Expected object of type (null) for property 'stringIds' on object of type 'Object', but received: 6011ea4dda6853a3af97376e'
 

Комментарии:

1. «но, похоже, это не так». что происходит?

2. Просто обновил вопрос с ошибкой, которую я получил @Alexander

3. В моем исходном коде я привел строку как NSPredicate(формат: filterString) Я просто не включил это в этот вопрос

4. Я ничего не знаю о realm, но filter метод Swift array просто не принимает NSPredicate. Но если это какой-то другой filter метод, который принимает NSPredicate, я бы спросил, можете ли вы использовать здесь предикат блока ? Их намного проще писать.

5. Можете ли вы показать пример блочного предиката?

Ответ №1:

Есть несколько проблем, которые необходимо решить.

Это

 let stringIds: [String]
 

не является объектом realm и не будет сохраняться в Realm.

Это должно быть свойство списка, а тип объекта списка — другой объект Realm. Списки областей не поддерживают примитивы (очень хорошо). Кроме того, не называйте свои объекты тем же именем, что и другой объект.

 class MyClass: Object {
    let myStringIdList = List<MyStringIdClass>
}
 

и

 class MyStringIdClass: Object {
   @objc dynamic var myId = ""
}
 

чтобы затем получить все объекты MyClass, у которых в их списке был определенный stringID

 let results = realm.objects(MyClass.self).filter("ANY myStringIdList.myId == %@", idToFind)
 

Строка внутри .filter также может быть NSPredicate, если это необходимо.

Вы также можете использовать LinkingObjects для перехода обратно к объектам MyClass.

Еще одна вещь, когда вы добавляете объекты realm в массив, они теряют связь с realm и больше не являются объектами обновления в реальном времени.

Кроме того, объекты области загружаются медленно, что означает, что тысячи объектов оказывают очень незначительное влияние на память. Однако приведение их к массиву загружает ВСЕ эти данные и может перегрузить устройство большим набором данных.

Комментарии:

1. Должен ли я помещать список идентификаторов строк в другой класс?

2. @MichaelJajou Взгляните на мой ответ в MyStringIdClass — идентификаторы строк хранятся в MyStringIdClass классе, и в MyClass есть их список.

3. Таким образом, нет способа сделать это, просто используя обычный список областей, а не создавая другой объект

4. @MichaelJajou Никоим образом не является субъективным. Вы можете хранить примитивы, но они не подлежат запросу, и при этом вы теряете много функциональности. Лучше всего использовать класс для хранения строки.