热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

UITableViewreloadData在iOS11中重新出现时崩溃

如何解决《UITableViewreloadData在iOS11中重新出现时崩溃》经验,为你挑选了1个好方法。

我认为之前有过类似的问题.不幸的是,他们都没有解决我面临的问题.

我的问题结构非常简单.我有两个视图控制器,比如VC1和VC2.在VC1中,我显示了一个UITableView中的一些项目列表,从数据库加载,在VC2中我显示了所选项目的详细信息,并进行编辑和保存.当用户从VC2返回VC1时,我必须重新填充数据源并重新加载表.VC1和VC2都嵌入在UINavigationController中.

听起来非常微不足道,确实是这样,直到我在UI线程中做了所有事情.问题是在VC1中加载列表有点费时.因此,我必须将繁重的数据加载任务委托给一些后台工作线程,并在数据加载完成时重新加载主线程上的表,以提供流畅的UI体验.所以我的初始构造类似于以下内容:

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    dispatch_async(self.application.commonWorkerQueue, ^{
        [self populateData]; //populate datasource
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.tableView reloadData]; //reload table view
        });
    });
}

这个功能非常实用,直到iOS10从viewWillAppear:停止立即渲染viewWillAppear开始,并开始将其viewWillAppear视为注册请求,以便prepareForSegue在运行循环的某些后续迭代中重新加载.所以我发现我的应用程序开始偶尔崩溃,如果UITableView在后续调用之前没有完成reloadData,这是非常明显的,因为reloadData不再是线程安全的,如果数据源在完成之前更改UITableView很可能会使应用程序崩溃.所以我尝试添加一个信号量以使[self.tableView reloadData]线程安全,我发现它工作得很好.我后来的构造类似于以下内容:

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    dispatch_async(self.application.commonWorkerQueue, ^{
        [self populateData]; //populate datasource
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.tableView reloadData]; //reload table view
            dispatch_async(dispatch_get_main_queue(), ^{
                dispatch_semaphore_signal(self.datasourceSyncSemaphore); //let the app know that it is free to repopulate datasource again
            });
        });
        dispatch_semaphore_wait(self.datasourceSyncSemaphore, DISPATCH_TIME_FOREVER); //wait on a semaphore so that datasource repopulation is blocked until tableView reloading completes
    });
}

不幸的是,自从iOS11 向下滚动[self populateData] VC1 ,这个结构也破,选择了一个调出VC2的项目,然后再回到VC1.它再次调用[self populateData]VC1,然后VC1尝试重新填充数据源reloadData.但是崩溃的堆栈跟踪显示UITableView已经开始从头开始重新创建它的单元格并且[self populateData]出于某种原因调用方法,甚至之前UITableView,我的数据源在后台重新填充,并且它处于某种不一致的状态.最终应用程序崩溃了.最令人惊讶的是,只有当我选择了最初不在屏幕上的底行时才会发生这种情况.以下是崩溃期间的堆栈跟踪:

崩溃的堆栈跟踪

我知道如果我从主线程中调用两个方法,一切都会正常运行,如下所示:

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self populateData]; //populate datasource
    [self.tableView reloadData]; //reload table view
}

但这不是预期的良好用户体验.我觉得问题发生了,因为viewWillAppear:在向下滚动时尝试在重新显示时获取屏幕外顶行.但不幸的是,在理解了这么多该死的东西后,我几乎无法解决这个问题.

我真的希望这个网站的专家能够帮助我摆脱困境,或者向我展示一些方法.感谢提前加载!

PS:[self populateData]是在此上下文中在后台运行的串行调度队列.



1> Rick..:

你应该拆分你的populateData功能.让我们说例如fetchDatabaseRowspopulateDataWithRows.本fetchDatabaseRows应在自己的线程和一个新的数据结构检索行到内存中.完成IO部分后,您应该在UI线程中调用populateDataWithRows(然后reloadData).populateDataWithRows应该修改TableView使用的集合.


推荐阅读
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • BZOJ1233 干草堆单调队列优化DP
    本文介绍了一个关于干草堆摆放的问题,通过使用单调队列来优化DP算法,求解最多可以叠几层干草堆。具体的解题思路和转移方程在文章中进行了详细说明,并给出了相应的代码示例。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 本文介绍了在使用Laravel和sqlsrv连接到SQL Server 2016时,如何在插入查询中使用输出子句,并返回所需的值。同时讨论了使用CreatedOn字段返回最近创建的行的解决方法以及使用Eloquent模型创建后,值正确插入数据库但没有返回uniqueidentifier字段的问题。最后给出了一个示例代码。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • 本文介绍了协程的概念和意义,以及使用greenlet、yield、asyncio、async/await等技术实现协程编程的方法。同时还介绍了事件循环的作用和使用方法,以及如何使用await关键字和Task对象来实现异步编程。最后还提供了一些快速上手的示例代码。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
author-avatar
灰包蛋啦_199
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有