#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 Никоим образом не является субъективным. Вы можете хранить примитивы, но они не подлежат запросу, и при этом вы теряете много функциональности. Лучше всего использовать класс для хранения строки.