iOS中NSRunloop与滚动视图时停止加载的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS中NSRunloop与滚动视图时停止加载的问题相关的知识,希望对你有一定的参考价值。

参考技术A 最早接触runloop的概念,是第一次用NSTimer的时候。一个最简单的例子:

如果我们同时在界面上滚动一个scrollview,那么我们会发现在滚动停止之前,控制台是不会有输出的,就好像scrollView在滚动的时候将timer暂停了一样。通过了解后发现,其实是Cocoa的RunLoop Mode在作怪。

我把runloop理解为一种cocoa下的一种消息循环的机制,用来处理各种消息事件。我们在开发的时候一般并不需要手动去创建一个runloop,因为在程序进入mainThread之后其实就为我们创建了默认的的mainRunLoop,通过[NSRunloop currentRunLoop]我们就可以得到当前线程对应的RunLoop对象,而我们需要留意的是在多个runloop之间消息的通知方式。

接上面说到的,开启一个NSTimer实质上是开启了一个新的线程(Runloop)在当前Runloop中注册了一个新的事件源,也就是说除了MainRunloop之外还有一个Runloop存在。而当scrollView在滚动的时候,当前MainRunLoop是处于UITrackingRunLoopMode,在该模式下,不会处理 NSDefaultRunLoopMode的消息(因为Runloop Model不一致),而NSTimer在创建后的RunLoop(B)默认会以NSDefaultRunLoopMode与当前context的Runloop(A)发送消息进行通信。要想在scrollView滚动的同时也接受其他runloop的消息,则需要改变两者之间的RunLoopMode。

类似的问题在前几天修改一个http异步通信模块的时候也碰到了,简单地说是向服务器异步获取图片数据后通知主线程刷新tableView中的图片,但在tableView滚动还没有停止或用户手指还停留在屏幕上的时候,图片一直不会出来。后来发现请求数据的时候用到了NSURLConnection的

了解后发现该方法创建的异步请求线程和NSTimer一样,也是NSDefaultRunLoopMode的,与

不同的是,上面的方法默认创建后默认直接发起请求,并以NSDefaultRunLoopMode与runloop进行消息传递,因此我们需要和NSTimer一样更改他的RunLoopMode。

StackOverFlow

Github Demo

参考: http://blog.csdn.net/xiazailushang/article/details/11930599

CollectionView 标题在滚动时停止刷新/重新加载数据

【中文标题】CollectionView 标题在滚动时停止刷新/重新加载数据【英文标题】:CollectionView header stop refreshing/ reloading data when is scrolled 【发布时间】:2017-06-12 11:14:36 【问题描述】:

有没有办法在集合视图中停止刷新我的标题上的数据? 我的集合视图中的标题包含不会将它们从视图中带走的数据和按钮。当您向下滚动时,集合视图会重新加载数据,并且我的集合视图标题上的任何激活按钮都会被停用。 如何在标题底部到达导航控制器下方之前停止刷新标题上的数据?或类似的东西,以便有足够的时间查看标题上的信息。

【问题讨论】:

问题解决了吗? 【参考方案1】:

如果您不想重新加载您的 collectionview,您可以使用 UICollectionView 的 reloadSectionsreloadItemsAtIndexpaths 内置方法

【讨论】:

【参考方案2】:

当你的标题结束显示时,它会调用你可以在隐藏后执行你的任务:-

func collectionView(collectionView: UICollectionView, didEndDisplayingSupplementaryView view: UICollectionReusableView, forElementOfKind elementKind: String, atIndexPath indexPath: NSIndexPath) 

你可以使用 dispatch_after 足够长的时间,比如 1 秒后你可以做任何事情:-

let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) 
    print("test")

【讨论】:

【参考方案3】:

你想停止重新加载collectionView的headerView,这是违反代码流的。不要这样做。

如何实现你的目标?

将它保存在任何地方。您可以使用 NSUserDefaults 来保存按钮的激活或停用状态。

【讨论】:

以上是关于iOS中NSRunloop与滚动视图时停止加载的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在快速向上和向下滚动表格时停止自动重新加载表格视图? [关闭]

iOS:当用户滚动表格视图时标签停止更新

如何在 CollectionView iOS 中停止自动重新加载和刷新图像

是否可以在 iOS 的 2 个滚动视图之间使用“reloadData”之类的东西来保持数据的有效加载?

滚动 UITableView 停止视频播放

如何知道滚动视图的对象在 iOS 的顶部?