首页 > 其他 > 详细

基础:block、runtime,runloop

时间:2017-01-18 15:06:35      阅读:361      评论:0      收藏:0      [点我收藏+]

block:http://www.imlifengfeng.com/blog/?p=457

对于 block 外的变量引用,block 默认是将其复制到其数据结构中来实现访问的。也就是说block的自动变量截获只针对block内部使用的自动变量, 不使用则不截获, 因为截获的自动变量会存储于block的结构体内部, 会导致block体积变大。特别要注意的是默认情况下block只能访问不能修改局部变量的值。

对于用 __block 修饰的外部变量引用,block 是复制其引用地址来实现访问的。block可以修改__block 修饰的外部变量的值。

  原因:一个局部变量加上__block修饰符后将变成了一个__Block_byref_val_0结构体类型的自动变量实例!!!!(此时局部变量和block是同一类型结构体)

  此时我们在block内部访问val变量则需要通过一个叫__forwarding的成员变量来间接访问val变量。

全局block相当于单例放在全局内存中;

Block不访问外界变量,放在代码段中,为全局块;

ARC 环境下:访问外界变量的 Block 默认存储在中(实际是放在栈区,然后ARC情况下自动又拷贝到堆区),自动释放。

Block的复制操作执行的是copy实例方法。Block只要调用了copy方法,栈块就会变成堆块。在ARC有效时,多次调用copy方法完全没有问题。

 

由于copy后block被复制到对上,此时栈上的__forwarding还是堆上的__forwarding指针都指向堆上的block,所以-----通过__forwarding, 无论是在block中还是 block外访问__block变量, 也不管该变量在栈上或堆上, 都能顺利地访问同一个__block变量。(访问的block变量唯一)

 

Category中不能添加成员变量:

Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针;objc_class结构体中,ivars是objc_ivar_list(成员变量列表)指针;methodLists是指向objc_method_list(方法定义的列表)指针的指针。在Runtime中,objc_class结构体大小是固定的,不可能往这个结构体中添加数据,只能修改。所以ivars指向的是一个固定区域,只能修改成员变量值,不能增加成员变量个数。methodList是一个二维数组,所以可以修改*methodLists的值来增加成员方法,虽没办法扩展methodLists指向的内存区域,却可以改变这个内存区域的值(存储的是指针)。因此,可以动态添加方法,不能添加成员变量。

 

  • Extension
    • 在编译器决议,是类的一部分,在编译器和头文件的@interface和实现文件里的@implement一起形成了一个完整的类。
    • 伴随着类的产生而产生,也随着类的消失而消失。
    • Extension一般用来隐藏类的私有消息,你必须有一个类的源码才能添加一个类的Extension,所以对于系统一些类,如NSString,就无法添加类扩展
  • Category
    • 是运行期决议的
    • 类扩展可以添加实例变量,分类不能添加实例变量
    • 原因:因为在运行期,对象的内存布局已经确定,如果添加实例变量会破坏类的内部布局,这对编译性语言是灾难性的。

 

FunLoop:http://www.imlifengfeng.com/blog/?p=487

程序运行,开启线程,为了保证程序持续运行,开启runloop,保证主线程不被销毁,在循环过程中处理对应的时间;我们可以把RunLoop看成一个死循环。

RunLoop对象包括Fundation中的NSRunLoop对象和CoreFoundation中的CFRunLoopRef对象。

(1)每条线程都有唯一的一个与之对应的RunLoop对象。

(2)主线程的RunLoop已经自动创建好了,子线程的RunLoop需要主动创建。

(3)RunLoop在第一次获取时创建,在线程结束时销毁。

线程和 RunLoop 之间是一一对应的,其关系是保存在一个全局的 Dictionary 里。线程刚创建时并没有 RunLoop,如果你不主动获取,那它一直都不会有。RunLoop 的创建是发生在第一次获取时,RunLoop 的销毁是发生在线程结束时。你只能在一个线程的内部获取其 RunLoop(主线程除外)。

[NSRunLoop currentRunLoop];方法调用时,会先看一下字典里有没有存子线程相对用的RunLoop,如果有则直接返回RunLoop,如果没有则会创建一个,并将与之对应的子线程存入字典中。

CFRunLoopModeRef

一个 RunLoop 包含若干个 Mode,每个 Mode 又包含若干个 Source/Timer/Observer。每次调用 RunLoop 的主函数时,只能指定其中一个 Mode,这个Mode被称作 CurrentMode。如果需要切换 Mode,只能退出 Loop,再重新指定一个 Mode 进入。这样做主要是为了分隔开不同组的 Source/Timer/Observer,让其互不影响。

 

instancetype和id:

(1)类方法中,以alloc或new开头
(2)实例方法中,以autorelease,init,retain或self开头
会返回一个方法所在类类型的对象,这些方法就被称为是关联返回类型的方法。换句话说,这些方法的返回结果以方法所在的类为类型。

非关联返回类型,可认为是非上面1、2两种方式而自定义的构造方法,得到的返回类型就和方法声明的返回类型一样,是id。

instancetype的作用,就是使那些非关联返回类型的方法返回所在类的类型

(1)id在编译的时候不能判断对象的真实类型

instancetype在编译的时候可以判断对象的真实类型

(2)如果init方法的返回值是instancetype,那么将返回值赋值给一个其它的对象会报一个警告

如果是在以前, init的返回值是id,那么将init返回的对象地址赋值给其它对象是不会报错的

(3)id可以用来定义变量, 可以作为返回值, 可以作为形参

instancetype只能用于作为返回值;

但凡自定义构造方法, 返回值尽量使用instancetype, 不要使用id。

基础:block、runtime,runloop

原文:http://www.cnblogs.com/hazhede/p/6296734.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!