NSRunloop小总结

本文详细介绍了Runloop的概念、用途及管理模式,包括RunLoop如何通过不同模式管理事件处理,以及在实际开发过程中遇到的问题及其解决方案。
一、概述

1.Run loops是线程的基础架构部分。一个run loop就是一个事件处理循环,用来不停的调配工作以及处理输入事件。使用run loop的目的是使你的线程在有工作的时候工作,没有的时候休眠。

2.Run loop的管理并不完全是自动的。你仍必须设计你的线程代码以在适当的时候启动run loop并正确响应输入事件。Cocoa和CoreFundation都提供了run loop对象方便配置和管理线程的run loop。你创建的程序不需要显示的创建run loop;任何线程,包含程序的主线程(main thread)都有与之相应的run loop对象。但是,自己创建的次线程是需要手动运行run loop的。在carbon和cocoa程序中,程序启动时,主线程会自行创建并运行run loop。

3.Run loop处理的输入事件有两种不同的来源:输入源(input source)和定时源(timer source)。输入源传递异步消息,通常来自于其他线程或者程序。定时源则传递同步消息,在特定时间或者一定的时间间隔发生。
除了处理输入源,run loop也会生成关于run loop行为的notification。注册的run-loop 观察者可以收到这些notification,并做相应的处理。可以使用Core Foundation在你的线程注册run-loop观察者。

二、Run Loop Modes

1.Run loop模式是所有要监视的输入源和定时源以及要通知的注册观察者的集合。每次运行run loop都会指定其运行在哪个模式下。以后,只有相应的源会被监视并允许接收他们传递的消息。(类似的,只有相应的观察者会收到通知)。其他模式关联的源只有在run loop运行在其模式下才会运行,否则处于暂停状态。

2.通常代码中通过指定名字来确定模式。Cocoa和core foundation定义了默认的以及一系列常用的模式,都是用字符串来标识。当然你也可以指定字符串来自定义模式。虽然你可以给模式指定任何名字,但是所有的模式内容都是相同的。你必须添加输入源,定时器或者run loop观察者到你定义的模式中。

3.通过指定模式可以使得run loop在某一阶段只关注感兴趣的源。大多数时候,run loop都是运行在系统定义的默认模式。但是模态面板(modal panel)可以运行在 “模态”模式下。在这种模式下,只有和模态面板相关的源可以传递消息给线程。对于次线程,可以使用自定义模式处理时间优先的操作,即屏蔽优先级低的源传递消息。

4.Note:模式区分基于事件的源而非事件的种类。例如,你不可以使用模式只选择处理鼠标按下或者键盘事件。你可以使用模式监听端口, 暂停定时器或者其他对源或者run loop观察者的处理,只要他们在当前模式下处于监听状态。

三、Run Loop Modes列表(由苹果官方文档翻译而来

1.NSDefaultRunLoopMode:大多数操作使用的默认模式,多数情况下你需要使用这个模式来开启你的run loop以及配置输入源。 NSTimer默认是使用这个模式部署的。

2.NSConnectionReplyModeCocoa使用这个模式来关联NSConnection去监听返回,你应该很少会使用这个模式。

3.NSModalPanelRunLoopModeCocoa使用这个模式来鉴定模态面板的时间目的。很少使用。

4.NSEventTrackingRunLoopMode当有鼠标操作或者其它用户跟踪交互时,Cocoa使用这个模式去限制其它输入事件。

5.NSRunLoopCommonModes:这是一个可配置的通用的模式组合,当将一个输入源跟这个模式关联,输入源将会和组合里面的所有模式关联。在Cocoa applications(主线程)中,这个组合默认包含Default,Modal,以及eventTrack。在Core Foundation(子线程)中,默认只包含default。可以通过CFRunLoopAddCommonMode来配置这个组合。

四、使用中遇到的问题:

1.问题一:
(1)场景说明:在一个ios应用中,使用NSTimer的默认方式(NSDefaultRunLoopMode模式下)初始化了一个定时器,或者以NSDefaultRunLoopMode方式在RunLoop上部署了网络请求(没有使用[connection scheduleInRunLoopXXXX]方法,默认都是Default),而此时发生了用户交互,例如发生了ScrollView滚动,此时主线程的RunLoop处在NSEventTrackingRunLoopMode模式下,其它的输入事件将会被屏蔽掉,导致定时器任务没有执行或者收不到网络请求回调。
(2)具体测试情况:(当用手一直滚动ScrollView或者手指不起来
<1>Timer:Timer的触法会被直接过滤掉,调用不会堆积。
<2>Connection:请求回调会收不到,短时间内停止交互,数据不会丢失,数据会累积等回调发生时一起返回,但是如果长时间不停止交互,请求会超时或者链接丢失。非用户主动发起的交互不会阻塞回调,例如通过代码自动发起的UI动画。
(3)解决办法:在此种情况下,需要将定时器或者网络请求以NSRunLoopCommonModes模式部署到RunLoop上,这样用户交互事件和其它输入事件就可以同时接收了。例如:
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

2.问题二:
(1)场景说明:在子线程中去发送异步请求,默认情况下收不到请求回调。
(2)解决办法:子线程有自动创建RunLoop,但是默认是没有运行的,在开始发送网络请求后,需要手动启动子线程的RunLoop,才能接收输入事件,并受到反馈。代码如下:
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值