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指向的内存区域,却可以改变这个内存区域的值(存储的是指针)。因此,可以动态添加方法,不能添加成员变量。
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,让其互不影响。
(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。
原文:http://www.cnblogs.com/hazhede/p/6296734.html