Uitableview fetchedResultsController对象的表视图部分

Uitableview fetchedResultsController对象的表视图部分,uitableview,core-data,nsfetchedresultscontroller,Uitableview,Core Data,Nsfetchedresultscontroller,我正在尝试为我的tableView数据编制索引,按姓名首字母排序列出的人的姓名。我已经看过很多关于如何使用一般的非持久性数据的教程,但是没有一个是关于核心数据的,也没有一个是关于如何使用fetchedResultsController选项(用于iCloud自动同步) 现在我的代码如下(为了清楚起见,我只转录与问题相关的部分): //从核心数据填充的两个数组,稍后用于填充表 var alumnosDictionaryArray=[String:[String]]() 变量tituloseccion

我正在尝试为我的tableView数据编制索引,按姓名首字母排序列出的人的姓名。我已经看过很多关于如何使用一般的非持久性数据的教程,但是没有一个是关于核心数据的,也没有一个是关于如何使用fetchedResultsController选项(用于iCloud自动同步)

现在我的代码如下(为了清楚起见,我只转录与问题相关的部分):

//从核心数据填充的两个数组,稍后用于填充表
var alumnosDictionaryArray=[String:[String]]()
变量tituloseccionarray=[String]()
重写func viewDidLoad(){
super.viewDidLoad()
//从核心数据中获取数据
updateFetchedResultsController()
//用这些数据填充数组
人口阵()
func updateFetchedResultsController(){
guard let context=container?.viewContext else{return}
context.performAndWait{
让sortDescriptor=NSSortDescriptor(键:“nombre”,升序:true)
request.sortDescriptors=[sortDescriptor]
fetchedResultsController=NSFetchedResultsController(fetchRequest:request,managedObjectContext:context,sectionNameKeyPath:nil,cacheName:nil)
做{
请尝试获取ResultsController?.performFetch()
tableView.reloadData()
}抓住{
打印(“获取数据时出错:\(错误)”)
}
}
}
func PopulateArray(){
如果let objects=fetchedResultsController?.fetchedObject{
对象中的校友{
让inicial=String(校友名?.prefix(1)?“”)
如果var值=alumnosDictionaryArray[inicial]{
values.append(alumno.nombre!)
alumnosDictionaryArray[inicial]=值
}否则{
校友字典雅雷[名字]=[校友名字!]
}
}
tituloseccionarray=[String](alumnosdirectionaryarray.keys)
tituloseccionarray=tituloseccionarray.sorted(按:{$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]
}
override func numberOfSections(在tableView:UITableView中)->Int{
返回tituloseccionarray.count
}
重写func tableView(tableView:UITableView,numberofrowsinssection:Int)->Int{
let inicial=tituloseccionarray[部分]
如果let values=alumnosDictionaryArray[inicial]{
返回值.count
}
返回0
}
重写func tableView(tableView:UITableView,cellForRowAt indexath:indexPath)->UITableViewCell{
让cell=tableView.dequeueReusableCell(标识符为“cell”,for:indexPath)作为!AlumnoCell
if self.validateIndexPath(indexPath){
让object=fetchedResultsController?.object(位于:indexPath)
让inicial=tituloseccionarray[indexPath.section]
如果let values=alumnosDictionaryArray[inicial]{
cell.nombreField.text=值[indexPath.section]
cell.specialidadfield.text=对象?.specialidarelacionada?.nombre
cell.cursoreld.text=对象?.cursoRelacionado?.nivel
cell.tutorField.text=对象?.tutorRelacionado?.nombre
}
}否则{
打印(“来自indexPath的错误”)
}
返回单元
}
//验证indexPath的步骤
func validateIndexPath(indexPath:indexPath)->Bool{
如果let sections=self.fetchedResultsController?.sections,
indexath.sectionString{
返回TITULOSSECIONARRAY[部分]
}
我得到了一个或多或少完整的表,表中有正确的节、节的标题(缩写)和每个节的行数,但似乎只有第一行起作用,因为其余的数据都是空的,在选择任何一行时都会抛出一个错误:“索引1处没有节”。事实上,我得到了许多“来自Indexath的错误”异常引发前控制台上的消息


有什么建议吗?谢谢。

对于
校友
实体,再添加一列
nombreFirstChar
。 然后使用类似的方法将此变量保存到数据库中:

alumno.nombreFirstChar = nombre.firstCharacter()
此处
firstCharacter
helper方法如下:

func firstCharacter() -> String {
    var firstCharacter = self.first ?? "#"
    
    if (!(firstCharacter >= "a" && firstCharacter <= "z") && !(firstCharacter >= "A" && firstCharacter <= "Z") ) {
        firstCharacter = "#"
    }
    return String(firstCharacter).capitalized
}
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
}

我相信如果您使用NSFetchedResultsController中内置的节功能,而不是尝试使用您自己的数组,那么这将更容易实现字段输入到我的对象中,然后在获取时将其用作节键路径。这样,可以直接从结果填充表视图。谢谢。请您给我一个更详细的示例。我从swift开始,不清楚您的想法。
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, managedObjectContext: context, sectionNameKeyPath: nombreFirstChar, cacheName: nil)
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
}