iOS知识问答

2019-11-30 作者:计算机教程   |   浏览(113)

iOS开发- reloadData无效 (子线程更新UI错误)

今天在写一个聊天工具的时候遇到了一个问题。

注册的通知里面, 每当有其他用户发来消息的时候, UITableView 就要重新更新

        cell.textLabel.textColor = [UIColor redColor];

使用红色标记cell名字来突出显示新消息。 (当然,, 这只是个demo, 效果比较渣。 正常情况应该是用户头像跳动或者显示新消息条数...)

可是我发现, 调用了这样的更新语句后, UITableVIew里面的数据并没有刷新。

- (void)sessionUpdated:(NSNotification *)notification
{
      [myTableView reloadData];
}

设了下断点, 发现没有回调其Delegate的numberOfRowsInSection和CellForRow,所以导致界面没有更新。

这就费解了。

然后我手动的拖拽UI Tableview, 使其重绘, 发现数据更新了。 正常显示, 变红。

说明逻辑是没错的。 只是调用了reloadData后每效果。

之后就是百度学习了。

总结如下:

**结论:

1、在子线程中是不能进行UI 更新的,而可以更新的结果只是一个幻像:因为子线程代码执行完毕了,又自动进入到了主线程,执行了子线程中的UI更新的函数栈,这中间的时间非常的短,就让大家误以为分线程可以更新UI。如果子线程一直在运行,则子线程中的UI更新的函数栈 主线程无法获知,即无法更新

2、只有极少数的UI能,因为开辟线程时会获取当前环境,如点击某个按钮,这个按钮响应的方法是开辟一个子线程,在子线程中对该按钮进行UI 更新是能及时的,如换标题,换背景图,但这没有任何意义永利电子游戏网站,**

故而, 更新UI要在主线程中执行, 把上述代码改成这样

- (void)sessionUpdated:(NSNotification *)notification
{
    dispatch_async(dispatch_get_main_queue(), ^{
                       [myTableView reloadData];
                       });

}

解决了问题。

http://www.bkjia.com/IOSjc/895211.htmlwww.bkjia.comtruehttp://www.bkjia.com/IOSjc/895211.htmlTechArticleiOS开发- reloadData无效 (子线程更新UI错误) 今天在写一个聊天工具的时候遇到了一个问题。 注册的通知里面, 每当有其他用户发来消息的时候...

  1. iOS为什么只能在主线程刷新UI ?
  2. 在NSObject中定义run实例方法,之后调用[NSObject performSelector:@selector(run)];会有问题吗?为什么?
  3. 关于Bundle目录的权限问题。

1. iOS 为什么只能在主线程刷新 UI ?

答:线程同步开销问题。GUI 操作非常复杂,为了性能,设计成只在一个线程里面进行操作,也就是主线程。如果在子线程中也能刷新 UI ,则 UI 操作需要进行加锁以保证线程同步,性能会大大下降。

那么为什么在子线程中刷新 UI 程序有时候不会崩溃呢?
分为两种情况

  1. 幻像,实际是在主线程刷新UI 。一般子线程生命周期短,子线程代码执行完毕后,又自动进入到了主线程,执行了子线程中的 UI 更新的函数栈。如果子线程一直在运行,则主线程无法获知子线程中的 UI 更新函数栈,也就无法刷新 UI 。
  2. 特殊情况。子线程在创建的时候获取了当前的图形上下文,这时候可以刷新 UI 界面。如点击某个按钮,这个按钮响应的方法是开辟一个子线程,在子线程中对该按钮进行 UI 更新是能及时的,如换标题、换背景图。

本文由永利电子游戏网站发布于计算机教程,转载请注明出处:iOS知识问答

关键词: