iOS高级开发runtime那点事实战(3)

添加类

1
2
3
4
5
6
7
8
9
10
11
12
objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)
添加类 superclass 类是父类 name 类的名字 size_t 类占的空间
void objc_disposeClassPair(Class cls) 销毁类
void objc_registerClassPair(Class cls) 注册类
objc_duplicateClass
Used by Foundation's Key-Value Observing.官方说法是不让自己调用
Do not call this function yourself.

具体代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void)allocClass{
Class clas = objc_allocateClassPair(NSClassFromString(@"FY"), "FYss", 0);
objc_property_attribute_t type = {"T", "@\"NSString\""};
objc_property_attribute_t ownership = { "C", "" };
objc_property_attribute_t backingivar = { "V", "_ivar1"};
objc_property_attribute_t attrs[] = {type, ownership, backingivar};
bool success = class_addProperty(clas, "nameIvar", attrs, 3);
if (success) {
NSLog(@"addIvar success");
if (class_isMetaClass(clas)) {
NSLog(@"是一个类");
}
}
objc_registerClassPair(clas);
[self printPropreListClass:clas];
}

实例化类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 创建类实例
id class_createInstance ( Class cls, size_t extraBytes );
// 在指定位置创建类实例
id objc_constructInstance ( Class cls, void *bytes );
// 销毁类实例
void * objc_destructInstance ( id obj );

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
id object_copy(id obj, size_t size) //拷贝obj
id object_dispose(id obj) //释放obj
Ivar object_setInstanceVariable(id obj, const char *name, void *value) //修改实例的值
Ivar object_getInstanceVariable(id obj, const char *name, void **outValue) //获取实例
OBJC_EXPORT void *object_getIndexedIvars(id obj) //获取obj的index
id object_getIvar(id object, Ivar ivar) //获取obj的ivar
void object_setIvar(id object, Ivar ivar, id value) //赋值ivar给obj默认值是value
const char *object_getClassName(id obj) //获取类的名字
Class object_getClass(id object) //获得 类
Class object_setClass(id object, Class cls) //把obj 改到cls的类下
int objc_getClassList(Class *buffer, int bufferLen) //获取class列表
Class *objc_copyClassList(unsigned int *outCount) //拷贝类数组
id objc_lookUpClass(const char *name) // 看看是否 注册了类
id objc_getClass(const char *name) //获取类
id objc_getRequiredClass(const char *name) //要是没有这个类就kill 这个类
const char * ivar_getName( Ivar ivar) //获取var的名字
const char * ivar_getTypeEncoding( Ivar ivar) //获取ivar 的 type
ptrdiff_t ivar_getOffset( Ivar ivar) //
void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy) //给类别添加 属性
id objc_getAssociatedObject(id object, void *key) //获取属性
void objc_removeAssociatedObjects(id object) //删除属性

发送消息

1
2
3
4
5
6
7
8
9
id objc_msgSend(id self, SEL op, ...)// id 发送消息给SEL op
double objc_msgSend_fpret(id self, SEL op, ...)// 和上边的一样这个用i386平台,PPC和PPC64不能用。
void objc_msgSend_stret(void * stretAddr, id theReceiver, SEL theSelector, ...)// 有返回值的消息 stretAddr 是返回值 theReceiver接收消息的id SEL 是方法名
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)//给父类方法发送消息
void objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...)//给父类添加消息

当我们用OC调用方法的时候,其实底层是obj发送消息的过程,就够obj发送消息给SEL,然后objruntime中会在objSELList中寻找,当然不是每次都去遍历所有的方法的,而是在methodCache,它会先去常用的方法cache在中查找,要是cache中没有这个方法,再去遍历所有的方法。参考:Runtime源码点这里

具体测试

1
2
3
4
5
6
7
objc_msgSend(self,@selector(msgTest));
-(void)msgTest{
NSLog(@"调用了我 objc_msgSend");
}
输出:2016-03-23 15:06:18.011 runTimeObj[46084:3861049] 调用了我 objc_msgSend
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
id method_invoke(id receiver, Method m, ...) 调用receiver的方法 id 不能是nil
void method_invoke_stret(id receiver, Method m, ...) //Using this function to call the implementation of a method is faster than calling method_getImplementation and method_getName. 官方描述就是比method_getNamemethod_getImplementation
IMP method_getImplementation( Method method) //指向IMP的方法指针
IMP是什么?本质上是一个指针,指向方法的指针,俗名就是函数指针。
const char * method_getTypeEncoding( Method method) //方法type 返回一个c字符串
char * method_copyReturnType( Method method) 方法返回的类型 一个c字符串 用完要free(char *)
unsigned method_getNumberOfArguments( Method method) //方法的元素数量
void method_getArgumentType( Method method, unsigned int index, char *dst, size_t dst_len) 获取method 索引是index的参数 值赋给dst 要是dst = nil;系统自动调用strncpy(dst, "", dst_len)
IMP method_setImplementation( Method method, IMP imp)imp赋给method
void method_exchangeImplementations( Method m1, Method m2) 交换两个方法
例如:IMP imp1 = method_getImplementation(m1);
IMP imp2 = method_getImplementation(m2);
method_setImplementation(m1, imp2);
method_setImplementation(m2, imp1);
const char * * objc_copyImageNames(unsigned int *outCount)//返回所有加载的Objective-C框架和动态库的名字。
const char *class_getImageName(Class cls)//获取class的动态库的名字
const char * *objc_copyClassNamesForImage(const char *image, unsigned int *outCount) //拷贝动态库
const char* sel_getName(SEL aSelector) //获取SEL的字符串名字
SEL sel_registerName(const char *str) //注册SEL 名字是str 返回注册成功的SEL
SEL sel_getUid(const char *str) //获取str的方法SEL指针
BOOL sel_isEqual(SEL lhs, SEL rhs) //判断两个SEL是否是同一个SEL

今天就到这吧,明天吧协议和属性看了。更多文章在www.fgyong.cn