简体   繁体   English

从Swift 4的核心数据对TableView中的数据进行分组

[英]Grouping Data in TableView from Core Data in Swift 4

I am having trouble finding out how to group my sections by a property in my Core Data database. 我在查找如何按核心数据数据库中的属性对我的部分进行分组方面遇到麻烦。 This is what my DB looks like here . 这是我的数据库看起来像在这里 I am trying to group my tableView by the dueDate property. 我正在尝试通过dueDate属性对tableView进行分组。 I have loaded up my Attributes in an array and that is how they are displayed. 我已经将属性加载到数组中,这就是它们的显示方式。 I plan on customizing the headers as well, so I would like to use the standard tableView methods. 我还计划自定义标题,因此我想使用标准的tableView方法。 Here is the code from my ViewController. 这是我的ViewController中的代码。

import UIKit
import CoreData

class MainTableViewController: UITableViewController {

    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    var taskArray = [Task]()

    override func viewDidAppear(_ animated: Bool) {
        loadData()
    }

    // MARK: - Table view functions
    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return taskArray.count
    }

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "Date"
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 65.00
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell", for: indexPath) as! TaskCell

        cell.nameLabel.text = taskArray[indexPath.row].name ?? "Add Items"

        if taskArray[indexPath.row].dueTime == nil {
            cell.timeLabel.text = ""
        } else {
            let timeFormatter = DateFormatter()
            timeFormatter.timeStyle = .short
            cell.timeLabel.text = timeFormatter.string(from: taskArray[indexPath.row].dueTime!)
        }

        return cell
    }

    // MARK: Add New Task
    @IBAction func addButtonPressed(_ sender: Any) {
        performSegue(withIdentifier: "newTaskSegue", sender: self)
    }


    // MARK: Save & Load Data
    func saveData() {
        do {
            try context.save()
        } catch {
            print("Error saving context \(error)")
        }
        tableView.reloadData()
    }

    func loadData() {
        let request : NSFetchRequest<Task> = Task.fetchRequest()
        let sort = NSSortDescriptor(key: "dueDate", ascending: false)
        let sort2 = NSSortDescriptor(key: "dueTime", ascending: false)
        request.sortDescriptors = [sort, sort2]

        do {
            taskArray = try context.fetch(request)
        } catch {
            print("Error loading data \(error)")
        }
        tableView.reloadData()
    }

}

Any help would be much appreciated. 任何帮助将非常感激。 Thanks! 谢谢!

You can easily group your data using NSFetchedResultsController . 您可以使用NSFetchedResultsController轻松将数据分组。 One parameter in the instantiation of NSFetchedResultsController specifically allows you to group your results into sections by passing the keyPath of an attribute that constitutes the predicate for section grouping. 在实例化一个参数NSFetchedResultsController明确允许您将您的结果段通过传递keyPath是成为部分分组谓词的属性。

Apple's documentation explains this pretty clearly, with example code: Apple的文档使用示例代码非常清楚地解释了这一点:

override func numberOfSections(in tableView: UITableView) -> Int {
    if let frc = <#Fetched results controller#> {
        return frc.sections!.count
    }
    return 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    guard let sections = self.<#Fetched results controller#>?.sections else {
        fatalError("No sections in fetchedResultsController")
    }
    let sectionInfo = sections[section]
    return sectionInfo.numberOfObjects
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = <#Get the cell#>
    guard let object = self.<#Fetched results controller#>?.object(at: indexPath) else {
        fatalError("Attempt to configure cell without a managed object")
    }
    // Configure the cell with data from the managed object.
    return cell
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    guard let sectionInfo = <#Fetched results controller#>?.sections?[section] else {
        return nil
    }
    return sectionInfo.name
}
override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
    return <#Fetched results controller#>?.sectionIndexTitles
}
override func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
    guard let result = <#Fetched results controller#>?.section(forSectionIndexTitle: title, at: index) else {
        fatalError("Unable to locate section for \(title) at index: \(index)")
    }
    return result
}

It is generally a Good Idea(tm) to use an NSFetchedResultsController when dealing with CoreData and UITableView or UICollectionView as you get handy notifications (through a NSFetchedResultsControllerDelegate ) when your data changes that allow you to insert or remove cells from your displayed view. 通常,在处理CoreData和UITableViewUICollectionView时,使用NSFetchedResultsController是一个好主意(tm),因为当数据发生更改时,您会收到方便的通知(通过NSFetchedResultsControllerDelegate ),从而可以从显示的视图中插入或删除单元格。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM