iOS - id && Object Messaging 深入讲解

来源:互联网 发布:matlab数据采集工具箱 编辑:程序博客网 时间:2024/05/21 10:54


(一)关于 id

在Objective-C,object有一个通用类型:id

id anObject;


上面这个定义仅仅只是标明了变量 anObject 是一个object(而不是int,double等基础类型),除此之外提供不了任何关于该object的类型信息(如果要得到该对象的更多信息,就要借助于isa 指针)。

在C或C++中,函数的返回值默认为int,而在Objective-C中,函数的返回值默认为id

id的定义如下:

typedef struct objc_object { Class isa;} *id;

因此每一个object都有一个isa,用于标明该object属于什么class。Class的定义如下:

typedef struct objc_class *Class;


编译器记录了每一个class的定义信息,runtime system会在运行时根据isa找到这些信息,比如:某个object属于哪个class,或者某个object能不能perform某个selector,或者找到它superclass的名字等。


(二)Object Messaging

1.奇怪的叫法:消息selector

在C语言中,我们说“调用某个函数”

int a = foo();

在C++中,我们说“某个object调用其某个成员方法”

int a = anObject.methodFunction();

在Object-C中,我们说 “给object发消息”

int a = [receiver message];

实际上,在Object-C中,所有的消息(也就是调用对象的方法)都是在运行时动态绑定的(C语言是编译时就确定好了函数地址)
[receiver message]


编译器会修改成对 objc_msgSend 的调用:

objc_msgSend(receiver, selector)


如果有参数,会是这样:

objc_msgSend(receiver, selector, arg1, arg2, ...)

注意:这个时候在叫法上,已经由 message 转换成 selector 了。

为什么叫 selector 呢?那是因为objc_msgSend会在这时候通过message 的名称,在一个叫做dispatch table 的表里 选择 message 对应的函数地址,找到这个函数地址后,将参数传递给该函数,并将该函数的返回值作为 objc_msgSend 的返回值返回给调用者。所以这里有一个“选择”的意味,于是乎被称作 selector 了。

因为可以继承,所以通过 selector 进行函数搜索时,可能会沿着继承链一直往上找,直到NSObject,如下图(来自apple官方):



当给object发送message后,objc_msgSend 会通过该object的isa指针找到自己的dispatch table如果没有找到对应的函数地址,会一直沿着继承链往上搜索。


2. Sending Messages to nil

The keyword nil is defined as a null object, an id with a value of 0. (按照 id 的定义,nil就是一个空指针喽~)

在Object-C中,给nil发message是合法的,且不会产生任何效果。但是对于返回值,还是有一些说法的:

1)如果message的返回值是object类型,那么当receiver为nil 时,返回值也是 nil

Person *motherInLaw = [[aPerson spouse] mother];

如果 [aPerson spouse] 返回nil,那么 [[aPerson spouse] mother] 返回nil

2)If the method returns any pointer type, any integer scalar of size less than or equal to sizeof(void*),a float, adouble, a long double, or a long long, then a message sent to nil returns 0.

3)If the method returns a struct, as defined by the Mac OS X ABI Function Call Guide to be returned in registers, then a message sent to nilreturns 0.0 for every field in the struct. Other struct data types will not be filled with zeros.

4)If the method returns anything other than the aforementioned value types, the return value of a message sent to nil isundefined.

示例:

id anObjectMaybeNil = nil;// this is validif ([anObjectMaybeNil methodThatReturnsADouble] == 0.0){ // implementation continues...}



0 0
原创粉丝点击