У меня есть объекты с собственностью NSDate, и мне нужно разбить их на два раздела (события первого - будущего, события второго - исторического), а затем для первого раздела мне нужно отсортировать их по дате свойство в порядке возрастания, а вторая - в порядке убывания. Любая идея, как сделать сортировку?NSFetchedResultsController различные дескрипторы сортировки для каждого раздела
ответ
Сначала установите свои сортировки дескрипторы в fetchRequest
func itemFetchRequest() -> NSFetchRequest{
let fetchRequest = NSFetchRequest(entityName: "Events")
let primarySortDescription = NSSortDescriptor(key: "futureEvents", ascending: true)
let secondarySortDescription = NSSortDescriptor(key: "historicEvents", ascending: false)
fetchRequest.sortDescriptors = [primarySortDescription, secondarySortDescription]
return fetchRequest
}
затем установите количество секций
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
let numberOfSections = frc.sections?.count
return numberOfSections!
}
и, наконец, ваши заголовки разделов
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String?{
let sectionHeader = Future Events
let sectionHeader1 = Historic Events
if (section== "0") {
return sectionHeader
} else {
return sectionHeader1
}
} else {
return nil
}
}
Предполагая, что вы используете NSFetchedResultsController
, базовая выборка должна быть отсортирована так или иначе. Я могу думать о двух разных решениях:
Используйте два отдельных FRCS, с дополнительными предикатами, так что один обрабатывает события прошлого, в то время как другие обрабатывают будущие события. Один будет отсортирован по возрастанию, другой - по убыванию. Проблема состоит в том, что оба FRC будут генерировать
indexPaths
для раздела 0. Поэтому вам необходимо переназначить второй код FRCindexPaths
, чтобы использовать раздел 1 таблицыView. Например, вcellForRowAtIndexPath
вам нужно будет что-то вроде этого:if (indexPath.section == 0) { objectToDisplay = self.futureFetchedResultsController.objectAtIndexPath(indexPath) } else { // use second FRC let frcIndexPath = NSIndexPath(forRow: indexPath.row, inSection: 0) objectToDisplay = self.pastFetchedResultsController.objectAtIndexPath(frcIndexPath) }
В качестве альтернативы, придерживаться одной FRC, сортируются по возрастанию. Тогда переназначить
indexPath
для второй секции, так что последний объект в разделе отображается в строке 0, и т.д.:if (indexPath.section == 0) { objectToDisplay = self.fetchedResultsController.objectAtIndexPath(indexPath) } else { // use remap to reverse sort order FRC let sectionInfo = self.fetchedResultsController.sections[1] as! NSFetchedResultsSectionInfo let sectionCount = sectionInfo.numberOfObjects let frcIndexPath = NSIndexPath(forRow: (sectionCount - 1 - indexPath.row), inSection:indexPath.section) objectToDisplay = self.fetchedResultsController.objectAtIndexPath(frcIndexPath) }
Лично я считаю, что второй вариант является предпочтительным. В каждом случае всем методам datasource/delegate tableView будет нужно одно и то же переназначение, и для методов делегатов FRC потребуется обратное сопоставление.
Чтобы решить общую проблему - желая различного упорядочения для каждого раздела, вы можете обернуть несколько объектов NSFetchedResultsController
в один объект, который выравнивает массивы секций в один массив и переназначает результаты таких функций, как func object(at: IndexPath)
, а также указателей в уведомлениях NSFetchedResultsControllerDelegate
.
Это позволит вам решить общую проблему, требующую отображения любого количества разделов, упорядоченных по-разному.
я был пойти на создание этого объекта обертку, и это, кажется, работает хорошо:
/**
A CompoundFetchedResultsController is a wrapper of a number of inner NSFetchedResultsControllers.
The wrapper flattens the sections produced by the inner controllers, behaving as if all sections
were fetched by a single controller. Additionally, change notifications are mapped before being
passed to the optional NSFetchedResultsControllerDelegate property, so that the section indices
in the notifications reflect the flattened section indicies.
Example use case: a table where sections should be ordered in mutually opposing ways. E.g., if
section 1 should be ordered by propery A ascending, but section 2 should be ordered by property A
descending. In this case, two controllers can be created - one ordering ascending, the other de-
scending - and wrapped in a CompoundFetchedResultsController. This will maintain the ease of use
in a UITableViewController, and the functionality provided by a NSFetchedResultsControllerDelegate.
*/
class CompoundFetchedResultsController<T: NSFetchRequestResult>: NSObject, NSFetchedResultsControllerDelegate {
// The wrapperd controllers
let controllers: [NSFetchedResultsController<T>]
// A delegate to notify of changes. Each of the controllers' delegates are set to this class,
// so that we can map the index paths in the notifications before forwarding to this delegate.
var delegate: NSFetchedResultsControllerDelegate? {
didSet { controllers.forEach{$0.delegate = self} }
}
init(controllers: NSFetchedResultsController<T>...) { self.controllers = controllers }
func performFetch() throws { controllers.forEach{try? $0.performFetch()} }
var sections: [NSFetchedResultsSectionInfo]? {
// To get the flattened sections array, we simply reduce-by-concatenation the inner controllers' sections arrays.
get { return controllers.flatMap{$0.sections}.reduce([], +) }
}
func object(at indexPath: IndexPath) -> T {
// Use the flattened sections array to get the object at the (flattened) index path
return sections![indexPath.section].objects![indexPath.row] as! T
}
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
// Forward on the willChange notification
delegate?.controllerWillChangeContent?(controller)
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
// Forward on the didChange notification
delegate?.controllerDidChangeContent?(controller)
}
private func sectionOffset(forController controller: NSFetchedResultsController<NSFetchRequestResult>) -> Int {
// Determine the index of the specified controller
let controllerIndex = controllers.index(of: controller as! NSFetchedResultsController<T>)!
// Count the number of sections present in all controllers up to (but not including) the supplied controller
return controllers.prefix(upTo: controllerIndex).map{$0.sections!.count}.reduce(0, +)
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
let sectionOffset = self.sectionOffset(forController: controller)
// Index Paths should be adjusted by adding to the section offset to the section index
func adjustIndexPath(_ indexPath: IndexPath?) -> IndexPath? {
guard let indexPath = indexPath else { return nil }
return IndexPath(row: indexPath.row, section: indexPath.section + sectionOffset)
}
// Forward on the notification with the adjusted index paths
delegate?.controller?(controller, didChange: anObject, at: adjustIndexPath(indexPath), for: type, newIndexPath: adjustIndexPath(newIndexPath))
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
let sectionOffset = self.sectionOffset(forController: controller)
// Forward on the notification with the adjusted section index
delegate?.controller?(controller, didChange: sectionInfo, atSectionIndex: sectionIndex + sectionOffset, for: type)
}
}
- 1. NSFetchedResultsController setLimit для каждого раздела
- 2. NSFetchedResultsController: сортировать дескрипторы и секции
- 3. Как изменить порядок раздела с помощью NSFetchedResultsController?
- 4. Используйте различные пользовательские ячейки для каждого раздела в UITableView
- 5. Имя пользовательского раздела Crashing NSFetchedResultsController
- 6. Проблема программирования сортировки раздела
- 7. Динамические строки для каждого раздела
- 8. UICollectionView макет для каждого раздела
- 9. падение дубликатами для каждого раздела
- 10. Различные сортировки
- 11. NSFetchedResultsController сортировки, используя атрибут ребенка
- 12. NSFetchedResultsController имя данного раздела найти индекс этого раздела
- 13. NSFetchedResultsController - как получить информацию из раздела NameForKeypath?
- 14. NSFetchedResultsController и NSPredicate и имя раздела
- 15. NSFetchedResultsController не обновляет индексы раздела UITableView
- 16. Использовать порядок сортировки с сервера в CoreData и передать NSFetchedResultsController без свойства для сортировки по
- 17. UITableViewController - Различное количество ячеек для каждого раздела
- 18. Настроить цвет рамки раздела UITableView для каждого раздела
- 19. XSLT вложенной сортировки/для каждого
- 20. Значение отношения Nil для ключевого пути раздела в nsfetchedresultscontroller
- 21. Различные строки для каждого блока
- 22. Различные настройки для каждого виджета
- 23. Различные анализаторы для каждого поля
- 24. Порядок сортировки EBean из раздела
- 25. Изменение сортировки в NSFetchedResultsController на лету
- 26. NSFetchedResultsController didChangeObject использует неправильную indexPath после сортировки
- 27. Различные способы печати раздела файла
- 28. Отзывчивое фоновое изображение для каждого раздела
- 29. indexpath.row перезапускается на 0 для каждого раздела
- 30. SQL Server уникальный ключ для каждого раздела
Какие futureEvents и ключи historicEvents? Объект Event имеет только одно свойство - date: NSDate –
Извините, я предположил, что у вас есть атрибут для двух, потому что вы хотели, чтобы они были заголовками разделов. Возможно, вам придется отделить их, если хотите, чтобы они были на отдельных разделах. –