如何解决fetchedResultsController对象的“表视图”部分
我正在尝试为tableView数据建立索引,并按其姓名首字母对所列出人员的姓名进行排序。我看过很多关于使用通用的所有非持久数据执行此操作的教程,但是没有关于Core Data以及使用fetchedResultsController选项(用于iCloud自动同步)的教程。
现在,我的代码如下(为清楚起见,我仅转录与问题相关的部分):
//The two arrays to populate from Core Data,used later to populate the table
var alumnosDictionaryArray = [String:[String]]()
var titulosSeccionArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
//Obtain data from Core Data
updateFetchedResultsController()
//Populate the arrays with this data
populateArrays()
func updateFetchedResultsController() {
guard let context = container?.viewContext else { return }
context.performAndWait {
let sortDescriptor = NSSortDescriptor(key: "nombre",ascending: true)
request.sortDescriptors = [sortDescriptor]
fetchedResultsController = NSFetchedResultsController<Alumno>(fetchRequest: request,managedobjectContext: context,sectionNameKeyPath: nil,cacheName: nil)
do {
try fetchedResultsController?.performFetch()
tableView.reloadData()
} catch {
print("Error obtaining data: \(error)")
}
}
}
func populateArrays() {
if let objects = fetchedResultsController?.fetchedobjects {
for alumno in objects {
let inicial = String(alumno.nombre?.prefix(1) ?? "")
if var values = alumnosDictionaryArray[inicial] {
values.append(alumno.nombre!)
alumnosDictionaryArray[inicial] = values
} else {
alumnosDictionaryArray[inicial] = [alumno.nombre!]
}
}
titulosSeccionArray = [String](alumnosDictionaryArray.keys)
titulosSeccionArray = titulosSeccionArray.sorted(by: {$0 < $1})
}
}
这部分工作正常,因为数组已经正确填充,就像我检查过打印语句一样。
稍后,用于表格数据:
override func numberOfSections(in tableView: UITableView) -> Int {
return titulosSeccionArray.count
}
override func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
let inicial = titulosSeccionArray[section]
if let values = alumnosDictionaryArray[inicial] {
return values.count
}
return 0
}
override func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",for: indexPath) as! AlumnoCell
if self.validateIndexPath(indexPath) {
let object = fetchedResultsController?.object(at: indexPath)
let inicial = titulosSeccionArray[indexPath.section]
if let values = alumnosDictionaryArray[inicial] {
cell.nombreField.text = values[indexPath.section]
cell.especialidadField.text = object?.especialidadRelacionada?.nombre
cell.cursoField.text = object?.cursoRelacionado?.nivel
cell.tutorField.text = object?.tutorRelacionado?.nombre
}
} else {
print("Error from indexPath")
}
return cell
}
//To validate indexPath
func validateIndexPath(_ indexPath: IndexPath) -> Bool {
if let sections = self.fetchedResultsController?.sections,indexPath.section < sections.count {
if indexPath.row < sections[indexPath.section].numberOfObjects {
return true
}
}
return false
}
override func tableView(_ tableView: UITableView,titleForHeaderInSection section: Int) -> String? {
return titulosSeccionArray[section]
}
我得到一个或多或少完整的表,其中包含正确的节,节的标题(缩写)以及每个行的行数,但似乎只有冷杉行有效,因为其余数据为空并抛出选择以下内容时发生错误:“索引1处无节”。实际上,在引发异常之前,控制台上会收到许多“来自indexPath的错误”消息。
有什么建议吗?谢谢。
解决方法
对于Alumno
实体,再增加nombreFirstChar
的一列。
然后使用类似的方法将此变量保存在数据库中:
alumno.nombreFirstChar = nombre.firstCharacter()
firstCharacter
辅助方法如下:
func firstCharacter() -> String {
var firstCharacter = self.first ?? "#"
if (!(firstCharacter >= "a" && firstCharacter <= "z") && !(firstCharacter >= "A" && firstCharacter <= "Z") ) {
firstCharacter = "#"
}
return String(firstCharacter).capitalized
}
现在在您的fetchedResultsController中,替换此行
fetchedResultsController = NSFetchedResultsController<Alumno>(fetchRequest: request,managedObjectContext: context,sectionNameKeyPath: nil,cacheName: nil)
使用
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "nombreFirstChar",ascending: true)]
fetchRequest.propertiesToGroupBy = ["nombreFirstChar"]
fetchedResultsController = NSFetchedResultsController<Alumno>(fetchRequest: request,sectionNameKeyPath: nombreFirstChar,cacheName: nil)
然后在表视图委托api中,可以像这样使用fetchedResultsController:
func numberOfSections(in tableView: UITableView) -> Int {
return fetchedResultsController.sections?.count ?? 0
}
func sectionIndexTitles(for tableView: UITableView) -> [String]? {
guard let fetchedResultsSections: [NSFetchedResultsSectionInfo] = channelFetchedResultsController.sections else {return nil}
return fetchedResultsSections!.map{String($0.name)}
}
func tableView(_ tableView: UITableView,titleForHeaderInSection section: Int) -> String? {
guard var fetchedResultsSections: [NSFetchedResultsSectionInfo] = fetchedResultsController.sections else {return nil}
return fetchedResultsSections[section].name
}
func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
guard var sections:[NSFetchedResultsSectionInfo] = fetchedResultsController.sections,let section = sections[section] else {
return 0
}
return section.numberOfObjects
}
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier,for: indexPath)
cell.accessoryType = .disclosureIndicator
let alumno = fetchedResultsController.object(at: indexPath)
...
return cell
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。