初探Runloop

1.runloop是什么?

runloop 是一个运行循环(死循环);

return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 该句代码默认会开启一个主线程

例证:


2.runloop有什么用?    

    (1)保证线程不退出


       我们知道线程结束的条件是,线程中未有未执行的任务

       所以为了保证主线程运转,执行 return UIApplicationMain(argc, argv, nil,      NSStringFromClass([AppDelegate class])); 该句代码创建了一个runloop

      注意:(1)主线程:是指app启动时第一个创建的线程,在该线程中才能执行UI有关操作,除此之外其实和其它子线程没有区分,(这也是为什么UI作为属性时,使用的是nonatomic)

   (2)负责监听事件:触摸事件、时钟事件、网络事件:


        案例   当滑动其他页面时,顶部轮播图不会轮播

3.runloop和多线程

  (1) 线程默认是不开启runloop的,线程不被cpu收回的前提是线程中有未执行完的任务


该线程开启后,不会执行eat方法 因为

(1)。线程已经死掉了(oc对象保留,但线程已经死掉了,因为未有未完成的任务(runloop没有开启))


正确的方法是:







4.runloop 性能优化(加载大图时,渲染图片像素较高)

问题:当用tableview显示高清图片时,如果一屏的高清图片过多,导致在一个runloop中渲染图片的时间过多,进而不能及时响应用户的滑动操作(在某个项目 *觅 中就出行过这种情况)导致滑动时显示出卡顿

注意:渲染图片属于runloop要做的事,滑动tableview也属于runloop要处理的事情,在一次性循环中,runloop既要渲染大量的高清图片又要响应拖拽事件,因此就会显得滑动卡顿

解决思路:让每个runloop中只渲染一张图片,这样就不会导致渲染很多图片后,才响应用户的滑动动作

步骤

1.添加观察runloop各个状态的观察者


2.把添加图片的代码加到一个数组中


3.添加一个间隔0.001秒的定时器,保证线程每个0.001秒就被唤醒 然后执行渲染图片的任务,因为时间间隔非常短,因此加载图片非常快


4.定时器进入休眠前执行渲染某一张图片的任务


注意点:

(1)观察runloop 要用到  CoreFoundation 框架中的 CFRunloop。 注意啦:CF是由C语言实现的,而不是Objective-C,所以如果用到了CF,就需要手动管理内存,ARC是无能为力的;

CF中遇到create、new、copy 要记得手动释放内存

例如:



(2)C语言中只能用函数指针来完成回调,OC中当然有很多方式:通知、block、代理、kvo


(3)桥接

先来说说「Core Foundation」(以下简称CF)的历史吧。当年乔布斯被自己创办的公司驱逐后,成立了「NeXT Computer」,其实做的还是老本行:卖电脑,但依旧不景气。好在NeXTSTEP系统表现还不错,亏损不至于太严重。正好此时苹果的市场份额大跌,急需一个新的操作系统,结果大家都知道了,乔布斯借此收购,重新回到了苹果。

这里就牵扯到了一个问题,如何让旧有的系统(Mac OS 9)和NeXTSTEP合成为一个新系统?这就需要一个更为底层的核心库可以供Mac Toolbox和OPENSTEP双方调用。CF就这么诞生了。

CF是由C语言实现的,而不是Objective-C,所以如果用到了CF,就需要手动管理内存,ARC是无能为力的。当然因为CF和Foundation之间的友好关系,它们之间的管理权也是可以移交的,这个后面再说。

Core Foundation框架(CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能。下面列举该框架支持进行管理的数据以及可提供的服务:

群体数据类型 (数组、集合等)

程序包

字符串管理

日期和时间管理

原始数据块管理

偏好管理

URL及数据流操作

线程和RunLoop

端口和soket通讯

Core Foundation框架和Foundation框架紧密相关,它们为相同功能提供接口,但Foundation框架提供Objective-C接口。如果您将Foundation对象和Core Foundation类型掺杂使用,则可利用两个框架之间的 “toll-free bridging”。所谓的Toll-free bridging是说您可以在某个框架的方法或函数同时使用Core Foundatio和Foundation 框架中的某些类型。很多数据类型支持这一特性,其中包括群体和字符串数据类型。每个框架的类和类型描述都会对某个对象是否为 toll-free bridged,应和什么对象桥接进行说明。


CoreFoundation 是C语言构成 而Foundation 是用OC把CoreFoundation进行包装了一遍

CoreFoundation 和 Foundation 之间相互转换就用到了桥接

桥接分为三种模式

第一种桥接方式  __bridge transfers a pointer between Objective-C and Core Foundation with no transfer of ownership.(这种方式只是传递了指针,而没有传递对象的所有权,也就是如果str销毁了,strC也不能用了)

CFStringRef strC = nil;

{

NSString *str = [NSString stringWithFormat:@"123"];

strC = (__bridge CFStringRef)(str);

}

NSLog(@"%@ ",strC);

第二种桥接方式  __bridge_retained or CFBridgingRetain casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you.You are responsible for calling CFRelease or a related function to relinquish ownership of the object.(这种方式只是用于OC对象转换为CF类型,它会将对象的所有权转移给strC,也就是说,即便str释放了,strC也可以使用

注意 在ARC条件下,如果使用__bridge_retained桥接,那么strC必须手动释放,因为桥接的时候已经将对象的所有转移给了strC,而C语言的东西是不归ARC管理的


NSString *str = [NSString stringWithFormat:@"123"];

CFStringRef strC = (__bridge_retained CFStringRef)str;

//CFStringRef StrC = CFBridgingRetain(str); 这一句和上面一句的效果一样

NSLog(@"%@ %@",str,strC);

CFRelease(strC);


第三种桥接方式  __bridge_transfer or CFBridgingRelease moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC.ARC is responsible for relinquishing ownership of the object.这种方式只是用于CF对象转换为OC类型,它会将对象的所有权转移给str,也就是说,即便strC释放了,str也可以使用

//注意 在ARC条件下,如果使用__bridge_transfer桥接,那么strC不用手动释放,因为__bridge_transfer会自动释放strC的

CFStringRef strC = CFStringCreateWithCString(nil, "456", kCFStringEncodingASCII);

NSString *str = (__bridge_transfer NSString*) (strC);

NSString *str = CFBridgingRelease(strC); //这一句和上面一句的效果一样

NSLog(@"%@ %@",str,strC);

CFRelease(strC);

总结

runloop和线程之间的关系

* 每个线程有且仅有一个对应的runloop,子线程的runloop默认是没有开启的,但是主线程的runloop默认是开启的

*runloop是懒加载,获得runloop等于开启runloop 例如:  [NSRunLoop currentRunLoop]

*runloop有5中mode(模式),但是主要的是两种模式:NSDefaultRunLoopMode(默认模式)和UITrackingUIRunLoopMode(界面追踪模式,也就是页面滑到时主线程会切换到UITrancking模式),要注意

**runloop启动时,只能有一种模式,要切换到另外一种模式,runloop要先退出再开启。

**每种模式都有source、定时器、observe三种触发模式,并且不同模式下,三种触发是相互隔离的,也就是说,比如定时器1加到NSDefault这种模式下了,那么当runloop启动时运行在UITrancking模式下事,就不会接收到定时器1的触发了

例如:NStimer定时滑动的问题,如果NStimer只加入到NSDefault模式下,那么当页面滑动时,主线程的runloop从default模式退出,开启UITrancking模式,但是NStimer并没有添加到UITrancking模式下,所以在滑动页面时,就收不到滑动的触发

参考

Core Foundation 框架 详解

苹果官方文档Toll-Free Bridged Types

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,064评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,606评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,011评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,550评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,465评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,919评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,428评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,075评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,208评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,185评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,191评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,914评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,482评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,585评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,825评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,194评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,703评论 2 339