NSFetchedResultsController填充并更改UITableView行和节时发生错误 应用数据 ViewControllers 目标结果错误代码

如何解决NSFetchedResultsController填充并更改UITableView行和节时发生错误 应用数据 ViewControllers 目标结果错误代码

首先让我说这是我第一次在Stack Overflow上发帖,这是我的第一个iOS应用程序。

应用

我和我的朋友们喜欢玩Carcassonne。我们决定开始一个正在进行的联赛,以跟踪获胜和得分。该应用程序跟踪这些游戏并在我们的群聊中分享结果。

数据

我正在使用CoreData存储三个实体:Season,Game和Player。这是它们的属性/关系: screenshot of xcdatamodel graph view.

ViewControllers

我跟随this guide将NSFetchedResultsController连接到UITableView。我的UITableViewControllers包装在导航控制器中。我的代码段如下。

目标

在导航控制器中导航后,能够在播放部分和基准部分之间切换玩家的情况(以防我在显示计分框后需要进行编辑)。

结果

期望:点击玩家名称应切换其isPlaying属性并将其在UITableView的两个部分之间移动。

实际:在离开并回到UITableView后点击播放器名称会使应用程序崩溃。

错误

Here is a video of the error.

我有tableView的didSelectRowAt切换Player的isPlaying布尔属性。 isPlaying将确定Player所在行将驻留在UITableView的哪个部分。创建新游戏时,可以将玩家从板凳部分(isPlaying = false)来回移动到游戏部分(isPlaying = true)。但是,当我离开该视图(例如,回到我的排名页面)并在导航控制器中返回到该视图时,当我尝试再次选择一行时,应用程序崩溃。

2020-08-28 11:53:04.354939-0400 FetchTest[5427:86101] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:],/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3920.31.102/UITableView.m:2108
2020-08-28 11:53:04.355249-0400 FetchTest[5427:86101] [error] fault: Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  attempt to delete row 4 from section 0 which only contains 4 rows before the update with userInfo (null)
CoreData: fault: Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  attempt to delete row 4 from section 0 which only contains 4 rows before the update with userInfo (null)
2020-08-28 11:53:04.355397-0400 FetchTest[5427:86101] [error] CoreData: Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  attempt to delete row 4 from section 0 which only contains 4 rows before the update with userInfo (null)
2020-08-28 11:53:04.357387-0400 FetchTest[5427:86101] [error] error: Serious application error.  Exception was caught during Core Data change processing.  This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.  attempt to delete row 4 from section 0 which only contains 4 rows before the update with userInfo (null)
CoreData: error: Serious application error.  Exception was caught during Core Data change processing.  This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.  attempt to delete row 4 from section 0 which only contains 4 rows before the update with userInfo (null)
2020-08-28 11:53:04.361285-0400 FetchTest[5427:86101] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException',reason: 'attempt to delete row 4 from section 0 which only contains 4 rows before the update'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff23e3de6e __exceptionPreprocess + 350
    1   libobjc.A.dylib                     0x00007fff512539b2 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff23e3dbe8 +[NSException raise:format:arguments:] + 88
    3   Foundation                          0x00007fff258d6bd2 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191
    4   UIKitCore                           0x00007fff4950188a -[UITableView _endCellAnimationsWithContext:] + 6824
    5   UIKitCore                           0x00007fff4951dace -[UITableView endUpdatesWithContext:] + 112
    6   FetchTest                           0x0000000109df538f $s9FetchTest29GameDetailTableViewControllerC26controllerDidChangeContentyySo016NSFetchedResultsG0CySo20NSFetchRequestResult_pGF + 287
    7   FetchTest                           0x0000000109df53f4 $s9FetchTest29GameDetailTableViewControllerC26controllerDidChangeContentyySo016NSFetchedResultsG0CySo20NSFetchRequestResult_pGFTo + 68
    8   CoreData                            0x00007fff23b7d69d __82-[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:]_block_invoke + 7591
    9   CoreData                            0x00007fff23a0338d developerSubmittedBlockToNSManagedObjectContextPerform + 154
    10  CoreData                            0x00007fff23a03274 -[NSManagedObjectContext performBlockAndWait:] + 197
    11  CoreData                            0x00007fff23b7b8e4 -[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:] + 105
    12  CoreFoundation                      0x00007fff23d68d2c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    13  CoreFoundation                      0x00007fff23d681a5 _CFXRegistrationPost1 + 421
    14  CoreFoundation                      0x00007fff23d67f11 ___CFXNotificationPost_block_invoke + 193
    15  CoreFoundation                      0x00007fff23e65473 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1795
    16  CoreFoundation                      0x00007fff23d67866 _CFXNotificationPost + 950
    17  Foundation                          0x00007fff2593826b -[NSNotificationCenter postNotificationName:object:userInfo:] + 59
    18  CoreData                            0x00007fff239efaa2 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 541
    19  CoreData                            0x00007fff23a9380f -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:deletions:updates:refreshes:deferrals:wasMerge:] + 1557
    20  CoreData                            0x00007fff239ea599 -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 1217
    21  CoreData                            0x00007fff239ed8ff -[NSManagedObjectContext save:] + 367
    22  FetchTest                           0x0000000109df0b33 $s9FetchTest29GameDetailTableViewControllerC9saveGamesyyF + 131
    23  FetchTest                           0x0000000109df02c7 $s9FetchTest29GameDetailTableViewControllerC05tableF0_14didSelectRowAtySo07UITableF0C_10Foundation9IndexPathVtF + 1543
    24  FetchTest                           0x0000000109df0427 $s9FetchTest29GameDetailTableViewControllerC05tableF0_14didSelectRowAtySo07UITableF0C_10Foundation9IndexPathVtFTo + 167
    25  UIKitCore                           0x00007fff495212de -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:isCellMultiSelect:] + 1354
    26  UIKitCore                           0x00007fff49520d7d -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 97
    27  UIKitCore                           0x00007fff495216be -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 334
    28  UIKitCore                           0x00007fff4932eb76 _runAfterCACommitDeferredBlocks + 352
    29  UIKitCore                           0x00007fff4931f304 _cleanUpAfterCAFlushAndRunDeferredBlocks + 248
    30  UIKitCore                           0x00007fff4934fb0d _afterCACommitHandler + 85
    31  CoreFoundation                      0x00007fff23da1087 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    32  CoreFoundation                      0x00007fff23d9bb3e __CFRunLoopDoObservers + 430
    33  CoreFoundation                      0x00007fff23d9c08a __CFRunLoopRun + 1226
    34  CoreFoundation                      0x00007fff23d9b8a4 CFRunLoopRunSpecific + 404
    35  GraphicsServices                    0x00007fff38c39bbe GSEventRunModal + 139
    36  UIKitCore                           0x00007fff49325968 UIApplicationMain + 1605
    37  FetchTest                           0x0000000109de0ceb main + 75
    38  libdyld.dylib                       0x00007fff520ce1fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

代码

我有:

var fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult>!

在课堂上和

initializeFetchedResultsController()

在viewDidLoad()中调用。

这是我的GameDetailTableViewController中的UITableView方法:

    override func numberOfSections(in tableView: UITableView) -> Int {
        return fetchedResultsController.sections!.count
        
    }
    
    override func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
        guard let sections = fetchedResultsController.sections else {
            fatalError("No sections in fetchedResultsController")
        }
        let sectionInfo = sections[section]
        
        return sectionInfo.numberOfObjects
    }
    
    override func tableView(_ tableView: UITableView,titleForHeaderInSection section: Int) -> String? {
        guard let sections = fetchedResultsController.sections else {
            fatalError("No sections in fetchedResultsController")
        }
        if sections[section].indexTitle == "0" {
            return "Bench"
        } else {
            return "Playing"
        }
    }
    
    override func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "gameDetailCell",for: indexPath) as! PlayerCell
        
        guard let object = self.fetchedResultsController?.object(at: indexPath) as? Player else {
            fatalError("Attempt to configure cell without a managed object")
        }
        
        cell.player = object
        
        cell.addDoneButtonOnKeyboard()
        
        //Set Name and Image
        
        if let name = object.name {
            cell.playerCellLabel.text = "\(name)"
            cell.playerImageView.image = maskRoundedImage(image: UIImage(named: name)!,radius: 15)
        }
        
        cell.playerScoreTextField.text = String(object.score)
        cell.playerScoreTextField.clearsOnBeginEditing = true
        cell.playerScoreTextField.delegate = self
        
        return cell
    }
    
    override func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath,animated: true)
        guard let object = self.fetchedResultsController?.object(at: indexPath) as? Player else {
            fatalError("Attempt to configure cell without a managed object")
        }
        
        print("Row \(indexPath.row) in section \(indexPath.section) was tapped.")
        
        
        object.isPlaying = !object.isPlaying
        saveGames()
 
    }

这是我的NSFetchedResultsController扩展。这基于上面链接的Apple指南。 (是的,使用initializeStandingsFetchedResultsController()并不是很干燥,这是我列表中的下一个。)我正在使用isPlaying布尔属性作为sectionNameKeyPath。

extension GameDetailTableViewController: NSFetchedResultsControllerDelegate {
    // MARK: - NSFetchedResultsController
    func initializeFetchedResultsController() {
        let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Player")
        let isPlayingSort = NSSortDescriptor(key: "isPlaying",ascending: false)
        let scoreSort = NSSortDescriptor(key: "score",ascending: false)
        request.sortDescriptors = [isPlayingSort,scoreSort]
        
        fetchedResultsController = NSFetchedResultsController(fetchRequest: request,managedObjectContext: K.context,sectionNameKeyPath: "isPlaying",cacheName: nil)
        fetchedResultsController.delegate = self
        
        fetchedResultsController.fetchRequest.predicate = NSPredicate(format: "game.dateCreated == %@",selectedGame!.dateCreated! as CVarArg)
        do {
            try fetchedResultsController.performFetch()
            
            playerArray = fetchedResultsController.fetchedObjects as! [Player]
            
        } catch {
            fatalError("Failed to initialize FetchedResultsController: \(error)")
        }
    }
    
    func initializeStandingsFetchedResultsController() {
        let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Player")
        let scoreSort = NSSortDescriptor(key: "score",ascending: false)
        request.sortDescriptors = [scoreSort]
        
        standingsFetchedResultsController = NSFetchedResultsController(fetchRequest: request,sectionNameKeyPath: nil,cacheName: nil)
        standingsFetchedResultsController.delegate = self
        
        standingsFetchedResultsController.fetchRequest.predicate = NSPredicate(format: "game.dateCreated == %@",selectedGame!.dateCreated! as CVarArg)
        do {
            try standingsFetchedResultsController.performFetch()
            
            
            standingsPlayerArray = standingsFetchedResultsController.fetchedObjects as! [NSManagedObject]
            
            
        } catch {
            fatalError("Failed to initialize FetchedResultsController: \(error)")
        }
    }
    
    // MARK: - NSFetchedResultsControllerDelegate Methods
    
    func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.beginUpdates()
    }
    
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,didChange sectionInfo: NSFetchedResultsSectionInfo,atSectionIndex sectionIndex: Int,for type: NSFetchedResultsChangeType) {
        switch type {
        case .insert:
            tableView.insertSections(IndexSet(integer: sectionIndex),with: .fade)
        case .delete:
            tableView.deleteSections(IndexSet(integer: sectionIndex),with: .fade)
        case .move:
            break
        case .update:
            break
        @unknown default:
            fatalError("You did something funky with the table view.")
        }
    }
    
    
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,didChange anObject: Any,at indexPath: IndexPath?,for type: NSFetchedResultsChangeType,newIndexPath: IndexPath?) {
        switch type {
        case .insert:
            tableView.insertRows(at: [newIndexPath!],with: .fade)
        case .delete:
            tableView.deleteRows(at: [indexPath!],with: .fade)
        case .update:
            tableView.reloadRows(at: [indexPath!],with: .fade)
        case .move:
            tableView.moveRow(at: indexPath!,to: newIndexPath!)
        @unknown default:
            fatalError("You did something funky with the table view.")
        }
    }
    
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.endUpdates()
    }
}</pre>

saveGames() is just this:
<pre>func saveGames() {
        do {
            try K.context.save()
        } catch {
            print("Error saving games. \(error)")
        }
    }</pre>
And my K.context is:
<pre>struct K {
    static let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
}

如上所述,这是我的第一个帖子和第一个应用程序。我是一个自学成才的程序员,只是学习iOS和Swift,所以请对我轻松一点:)

解决方法

我的控制器didChange anObject(在NSFetchedResultsControllerDelegate方法部分中)针对相同的indexPath触发了.move和.update。 .move触发后,该indexPath上不再存在任何对象,因此.update失败。

这就是为什么它仅在点击视频的最后一行时才会失败。对于我的代码,我没有使用.update,所以我将其注释掉了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-