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

时间:2019-01-10 22:03:41

标签: ios swift uitableview core-data

我在查找如何按“核心数据”数据库中的属性对部分进行分组方面遇到麻烦。这就是我的数据库here的样子。我正在尝试通过dueDate属性对tableView进行分组。我已经将属性加载到数组中,这就是它们的显示方式。我还计划自定义标题,因此我想使用标准的tableView方法。这是我的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()
    }

}

任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:0)

您可以使用NSFetchedResultsController轻松地对数据进行分组。实例化NSFetchedResultsController中的一个参数特别允许您通过传递构成部分分组谓词的属性keyPath将结果分组为部分。

Apple的documentation用示例代码非常清楚地解释了这一点:

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
}

在处理CoreData和UITableViewUICollectionView时,使用NSFetchedResultsController通常是一个好主意(tm),因为当数据更改时(通过NSFetchedResultsControllerDelegate)会收到方便的通知(通过class Inventory extends Component { state = { items: [], item: [], pagination: {}, loading: false }; handleItemSelect = (itemId) => { const Items = this.state.items; let item = this.state.item; let newItem = []; newItem = Items.find(itemById => itemById._id === itemId); this.setState({ item: newItem }); console.log(itemId); console.log(item); }; fetchItems = () => { this.setState({ loading: true }); fetch(`http://localhost:5000/api/items`, { method: "GET" }) .then(response => response.json()) .then(items => { // console.log(items, items.length); const pagination = { ...this.state.pagination }; //Read total count from server pagination.total = items.length; this.setState({ loading: false, items: items, pagination }); }) .catch(err => console.log(err)); }; componentDidMount() { this.fetchItems(); } render() { const topColResponsiveProps = { xs: 24, sm: 12, md: 12, lg: 12, xl: 6 }; const { items, item } = this.state; return ( <React.Fragment> <h2>Inventory - [Receive Stock]</h2> <Row type="flex" justify="space-around"> <Column {...topColResponsiveProps}> <Card title="Item Details"> <FormItem label="Item Name:"> <Select showSearch style={{ width: "100%" }} placeholder="Select Item" optionFilterProp="children" onChange={this.handleItemSelect} filterOption={(input, option) => option.props.children .toLowerCase() .indexOf(input.toLowerCase()) >= 0 } > {items.map(item => ( <Option key={item._id} value={item._id}> {item.item_name} </Option> ))} </Select> </FormItem> <FormItem label="Category:"> <Select showSearch style={{ width: "100%" }} placeholder="Select category" optionFilterProp="children" filterOption={(input, option) => option.props.children .toLowerCase() .indexOf(input.toLowerCase()) >= 0 } > {item.map(itemCat => ( <Option key={itemCat._id}>{itemCat.category_name}</Option> ))} </Select> </FormItem> </Card> </Column> </Row> </React.Fragment> ); )允许您从显示的视图中插入或删除单元格。