#ios #swift #core-data #nspredicate
#iOS #swift #core-data #nspredicate
Вопрос:
У меня есть две модели: альбом и песня, альбом содержит N песен, но песня содержит только 1 альбом. Я пытаюсь создать конкретный фильтр, но я не смог найти NSPredicate, который дает мне ожидаемые результаты.
Я создал обе модели в CoreData:
Итак, я создал несколько объектов:
let song1 = Song(context: context)
song1.name = "I Love You"
song1.composer = "Ana"
let song2 = Song(context: context)
song2.name = "Hello And Goodbye"
song2.composer = "Ben"
let song3 = Song(context: context)
song3.name = "I Miss You"
song3.composer = "Marie"
let song4 = Song(context: context)
song4.name = "Lonely"
song4.composer = "Ana"
let album = Album(context: context)
album.name = "Love Songs 1"
let set = NSSet(array: [song1, song2, song3])
album.addToSong(set)
let album2 = Album(context: context)
album2.name = "Love Songs 2"
let set2 = NSSet(array: [song4])
album2.addToSong(set2)
Итак, я хотел бы выполнить этот фильтр:
Получить альбомы, где Ana является композитором, А название песни содержит «n»
Я извлекаю модель Albums с этим предикатом:
let composerPredicate = NSPredicate(format: "ANY song.composer = %@", "Ana")
let songPredicate = NSPredicate(format: "ANY song.name contains %@", "n")
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [composerPredicate, songPredicate])
Но в полученных результатах я получил оба альбома, но я хотел бы вернуть мне только «Песни о любви 2».
Вы знаете, как я мог бы это сделать?
ПРАВКА1: Я хотел бы найти решение, которое не использует никаких карт, фильтров или циклов (если это возможно), потому что это напрямую влияет на производительность, потому что я имею дело с большим количеством данных.
Комментарии:
1.
Song2
имеетn
в названии, поэтому оба альбома должны быть возвращены, поскольку вы используетеANY
2. Я не могу удалить ANY, потому что он выходит из строя с этой ошибкой: «Завершение работы приложения из-за неперехваченного исключения ‘NSInvalidArgumentException’, причина: ‘ключ to-many здесь не разрешен'»
Ответ №1:
Вам нужно использовать ПОДЗАПРОС, потому что вы хотите включить альбом, только если в нем есть песня, соответствующая обоим критериям. (Ваш составной предикат будет включать альбом, в котором есть одна песня, соответствующая первому критерию, и другая песня, соответствующая второму критерию).
let predicate = NSPredicate(format: "SUBQUERY(song, $S, $S.composer == %@ AND $S.name contains %@).@count > 0", “Ana”, "n")
Комментарии:
1. Это отлично сработало для моей проблемы! Большое спасибо! Я никогда раньше не использовал подзапросы, поэтому не знал, что это может быть решением.
2. Вы знаете, как я мог бы отсортировать альбомы по названию песни? Также используются предикаты или sortDescriptors.
3. Вы не можете сортировать альбомы по названию песни, потому что в каждом альбоме много песен. Вы можете сортировать только по атрибуту или отношению «к одному».