iOS - id && Object Messaging 深入讲解


(一)关于 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, a double, 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 nil returns 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 is undefined.

示例:

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值