У меня вопрос по CoreData.
Допустим, у меня есть 2 объекта CoreData SchoolClass и Child в базе данных CoreData, в которой есть несколько школьных классов, каждый класс с несколькими детьми.
extension SchoolClass {
…
@NSManaged public var children: NSSet?
…
}
extension Child {
…
@NSManaged public var schoolClass: SchoolClass?
@NSManaged public var age: Int?
…
}
С одной точки моего приложения я должен получить всех дочерних элементов определенного класса, которые соответствуют определенным дополнительным критериям.
Я вижу два способа сделать это:
extension SchoolClass {
…
var filteredChildren: [Child] {
let set = children as? Set<Child> ?? []
let filteredSet = set.filter{ $0.age < 10}
return filteredSet
}
…
}
let fetchRequest: NSFetchRequest<Child> = Child.fetchRequest()
let predicate1 = NSPredicate(format: "schoolClass === %@", targetSchoolclass)
let predicate2 = NSPredicate(format: "age < 10")
let predicate = NSCompoundPredicate(type: .and, subpredicate: [predicate1, predicate2])
fetchRequest.predicate = predicate
if let fetchedChildren = try? context.fetch(fetchRequest) {
…
}
Какой из них более целесообразен? Первый мне кажется более логичным, так как он должен проверять только детей в конкретном интересующем меня школьном классе. С другой стороны, я не очень понимаю, какая магия происходит за кулисами CoreData fetchRequest.
Но первый может быть лучше, если у вас уже есть объект SchoolClass в памяти и, возможно, даже объекты Child. Так что это зависит от многих вещей, таких как структура приложения и то, как вы используете свои данные, сколько дочерних объектов обычно имеет SchoolClass и т. д. и т. д.





Первый быстрее. Запрос связи выполняется быстрее, поскольку она уже проиндексирована и может уже находиться в памяти. Даже если у вас ОЧЕНЬ большой набор возможных детей и вы хотите, чтобы в наборе было только несколько, отношения все равно будут намного быстрее. У меня лично была аналогичная ситуация с запросом всех сообщений, отправленных пользователем в приложении чата. Несмотря на то, что большинство сообщений не было в конкретном чате, который меня интересовал, постановка в очередь отношений - а не новая выборка - была на порядки быстрее.
Вы можете легко убедиться в этом сами, загрузив тысячу поддельных сущностей, а затем оцените разницу между ошибкой, фильтрацией отношения и выборкой.
Спасибо, Джон, это прояснило для меня ситуацию!
Второй оптимизирован, потому что вы выбираете только нужных детей, а в первом вы выбираете все, а затем оставляете только нужный.
NSPredicate— это просто способ фильтрации. Можно добавить флаг, чтобы видеть "SQL запрос", фильтрацию лучше делать в запросе