iOS进阶之对象与方法的本质(二)

292 阅读2分钟

更多文章请点击下方:

  1. iOS进阶之Runtime初探(一)
  2. iOS进阶之方法查找(三)
  3. iOS进阶之动态方法解析(四)
  4. iOS进阶之消息转发(五)

引言

我们知道Objective-C提供的运行时,对于同一个函数,放在c语言中如果没有实现这个函数,编译是会报错的,但对于OC仅仅声明此方法,并未实现,编译是不会报错的,但只有程序运行后才会报错。 其实,我们runtime底层会提供很多方法。

接下来我们先阐述一下oc对象

对象

我们代码编写创建一个对象,通过Clang命令来进行编译生成.cpp文件

clang -rewrite-objc xxx.m -o xxx.cpp

查看该文件,会发现创建对象的该类的定义

typedef struct objc_object CuctomClass;

如代码所示,对象的本质是一个结构体。

方法

对象初始化代码如下:

CuctomClass *p = ((CuctomClass *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("CuctomClass"), sel_registerName("new"));

如代码所示,方法的本质就是发送消息,接下来我们通过对象发送一个消息。

每个消息都会调用objc_msgsend

 ((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("run"));

第一对象是Objc强制转换,代表消息接收者(void (*)(id, SEL))(void *)objc_msgSend)((id)p 第二参数代码方法编号sel_registerName("run") 其实是一个字符串

方法调用的过程其实就是通过方法编号SEL找到底层对应的IMP(函数实现的指针)。

Runtime 调用的方式

  1. Runtime 提供的API,请参考:Runtime API
  2. NSObject 提供的API,如:isKindOf、isMemberOf
  3. 编译器提供Oc上层方法,如:@seletor

类方法

类方法的调用,如下代码:

id cls = [CustomeClass class];
void *pointA = &cls;
[(__bridge id)pointA run];
objc_msgSend(objc_getclass("CustomeClass"), sel_registerName("run"));

类方法存在元类,对象方法存在类,类存在元类,都是以实例方法形式存在的

有一幅经典isa走位图: