Runloop是事件接收和分发机制的一个实现。 Runloop提供了一种异步执行代码的机制,不能并行执行任务。 在主队列中,Main RunLoop直接配合任务的执行,负责处理UI事件、定时器以及其他内核相关事件。
Runloop工作的特点:
1>当有时间发生时,Runloop会根据具体的事件类型通知应用程序作出相应; 2>当没有事件发生时,Runloop会进入休眠状态,从而达到省电的目的; 3>当事件再次发生时,Runloop会被重新唤醒,处理事件.提示:一般在开发中很少会主动创建Runloop,而通常会把事件添加到Runloop中.
obj对象继承NSObject,其内容如下:
@interface NSObject <nsobject> { Class isa OBJC_ISA_AVAILABILITY; }</nsobject>isa:是一个Class 类型的指针. 每个实例对象有个isa的指针,他指向对象的类,而Class里也有个isa的指针, 指向meteClass(元类)。元类保存了类方法的列表。当类方法被调用时,先会从本身查找类方法的实现,如果没有,元类会向他父类查找该方法。 所以Class的内容如下:
typedef struct objc_class *Class; struct objc_class { Class isa; // 指向metaclass Class super_class ; // 指向其父类 const charchar *name ; // 类名 long version ; // 类的版本信息,初始化默认为0,可以通过runtime函数class_setVersion和class_getVersion进行修改、读取 long info; // 一些标识信息,如CLS_CLASS (0x1L) 表示该类为普通 class ,其中包含对象方法和成员变量;CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法; long instance_size ; // 该类的实例变量大小(包括从父类继承下来的实例变量); struct objc_ivar_list *ivars; // 用于存储每个成员变量的地址 struct objc_method_list **methodLists ; // 与 info 的一些标志位有关,如CLS_CLASS (0x1L),则存储对象方法,如CLS_META (0x2L),则存储类方法; struct objc_cache *cache; // 指向最近使用的方法的指针,用于提升效率; struct objc_protocol_list *protocols; // 存储该类遵守的协议 } 而选择器@selector()主要作用是快速的通过方法名字(doSomeThing)查找到对应方法的函数指针,然后调用其函数。SEL其本身是一个Int类型的一个地址,地址中存放着方法的名字。对于一个类中。每一个方法对应着一个SEL。所以iOS类中不能存在2个名称相同的方法,即使参数类型不同,因为SEL是根据方法名字生成的,相同的方法名称只能对应一个SEL。由此可以得出整个过程为 1.编译器将代码[obj doSomeThing];转化为objc_msgSend(obj, @selector (doSomeThing));, 2.在objc_msgSend函数中。首先通过obj的isa指针找到obj对应的class。 3.在class中先去cache中通过SEL查找对应函数method(猜测cache中method列表是以SEL为key通过hash表来存储的,这样能提高函数查找速度) 4.若cache中未找到。再去methodList中查找,若methodlist中未找到,则取superClass中查找。若能找到,则将method加入到cache中,以方便下次查找,并通过method中的函数指针跳转到对应的函数中去执行。
