我在查找如何按“核心数据”数据库中的属性对部分进行分组方面遇到麻烦。这就是我的数据库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()
}
}
任何帮助将不胜感激。谢谢!
答案 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和UITableView
或UICollectionView
时,使用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>
);
)允许您从显示的视图中插入或删除单元格。