《招一个靠谱的iOS》16-20

本人参考GitHub《招聘一个靠谱的iOS》面试题参考答案(上)
16. @synthesize合成实例变量的规则是什么?假如property名为foo,存在一个名为_foo的实例变量,那么还会自动合成新变量么?
17. 在有了自动合成属性实例变量之后,@synthesize还有哪些使用场景?
18. objc中向一个nil对象发送消息将会发生什么?
19. objc中向一个对象发送消息[obj foo]和objc_msgSend()函数之间有什么关系?
20. 什么时候会报unrecognized selector的异常?

16. @synthesize合成实例变量的规则是什么?假如property名为foo,存在一个名为_foo的实例变量,那么还会自动合成新变量么?

科普一个概念:
实例变量 = 成员变量 = ivar
如果使用了属性的话,那么编译器就会自动编写访问属性所需的方法,此过程叫做“自动合成”(auto synthesis)。这个过程由编译器在编译期执行,除了生成方法代码之外,编译器还要自动向类中添加适当类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。

@interface Person : NSObject
@property NSString *firstName;
@property NSString *lastName;
@end

在上例中,会生成两个实例变量,其名称分别为_firstName和_lastName。也可以在类的实现代码中通过@synthesize语法来指定实例变量的名字。

@implementation
@synthesize firstName = _myFirstName;
@synthesize lastName = _myLastName;
@end

上述语法会将生成的实例变量命名为_myFirstName和_myLastName,而不再是默认的_firstName和_lastName。
总结一下,@synthesize合成实例变量的规则,有以下几点:

  1. 如果没有指定成员变量的名称就会自动生成一个属性同名的加_的成员变量;
    即,@synthesize foo;则生成名称为_foo的成员变量。
  2. 如果指定了成员变量的名称,会生成一个指定名称的成员变量;
    即,'@synthesize foo = _myFoo'则生成一个名称为_myFoo的成员变量。
  3. 如果这个成员变量已经存在了,就不再生成新的变量了;
@interface Person : NSObject
{
    NSString *_firstName;
}
@property (nonatomic, copy) NSString *firstName;

此时,由于已存在名为_firstName的成员变量,就不再为firstName属性合成新的成员变量了。

17. 在有了自动合成属性实例变量后,@synthesize还有哪些使用场景?

在回答这个问题前,先搞清楚一个问题:什么时候不会autosynthesis(自动合成),即不自动生成成员变量?
1.同时重写了setter和getter时;
2.重写了只读属性的getter时;
3.使用了@dynamic时;
4.@protocol中定义的所有属性;
5.在category中定义的所有属性;
6.重载的属性。
所以,使用@synthesize场景:
1.同时重写了setter和getter时,系统不再自动合成,需使用@synthesize合成;
2.重写了只读属性的getter时,系统不再自动合成,需使用@synthesize合成;
3.不使用默认名称的实例变量进行合成,而是使用自定义名称的成员变量进行合成;
4.遵守协议的类,实现协议中的成员变量。

18. objc中向一个nil对象发送消息将会发生什么?

在Objective-C中向nil发送消息是完全有效的,只是在运行时不会有任何作用:
Person *mother = [[Person spouse] mother];
如果spouse对象是nil,那么发送给nil(spouse)的消息mother也将放回nil。
向nil发送消息分为以下几种情况:

  1. 如果一个方法返回值是一个对象,那么发送给nil的消息将返回0(nil);
  2. 如果方法返回值为指针类型,其指针大小为小于或者等于sizeof(void *),float,double,long double或者long long的整型标量,发送给nil的消息将返回0;
  3. 如果方法返回值为结构体,发送给nil的消息将返回0。结构体中各个字段的值都将是0;
  4. 如果方法的返回值不是上述提到的几种情况,那么发送给nil的消息的返回值将是未定义的。
    类在runtime中的源代码:
struct objc_class
{
    Class isa OBJC_ISA_AVAILABILITY; // 类的isa指针指向Meta Class,因为Objc的类的本身也是一个Object,为了处理这个关系,runtime就创造了Meta Class,当给类发送[NSObject alloc]这样的消息时,实际上是把这个消息发给了Class Object
    #if !__OBJC2__
    Class super_class OBJC2_UNAVAILABLE; // 父类
    const char *name OBJC2_UNAVAILABLE; // 类名
    long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
    long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识
    long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小
    struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表
    struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表
    struct objc_cache *cache OBJC_UNAVAILABLE; // 方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在method Lists中遍历,如果cache了,常用的方法调用时就能够提高调用的效率
    struct objc_protocol_list *portocols OBJC2_UNAVAILABLE;// 协议链表
    #endif
} OBJC2_UNAVAILABLE;

Objective-C在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实际所属的类,然后在该类中的方法列表以及其父类方法列表中寻找该方法进行运行。在发送消息的时候,objc_msgSend方法不会返回值,所谓的返回内容都是具体调用时执行的。如果向一个nil对象发送消息,首先在寻找对象的isa指针时就是0地址返回了,所以不会出现任何错误。

19. objc中向一个对象发送消息[obj foo]和objc_msgSend()函数之间有什么关系?

[objc foo]在编译之后就是objc_msgSend()函数调用。

20. 什么时候会报unrecognized selector异常?

当调用该对象的某个方法,而该对象没有实现这个方法的时候会报unrecognized selector异常。
Objective-C是动态语言,每个方法在运行时会被动态转为消息发送,即:Objc_msgSend(receiver, selector);
Objective-C在向一个对象发送消息时,runtime会根据对象的isa指针找到该对象实际所属的类,然后在该类中的方法列表以及其父类的方法列表中寻找该方法运行。如果,在最顶层的父类中依然找不到相应的方法,程序会在运行时挂掉并抛出异常unrecognized selector sent to XXX。但是在这之前,Objective-C的运行时有三次拯救程序崩溃的机会。

  1. Method resolution(方法解析)
    Objective-C运行时会调用+ (BOOL)resolveInstanceMethod:(SEL)sel或者+ (BOOL)resolveClassMethod:(SEL)sel,让开发者有机会提供一个函数实现。如果开发者添加了函数,那运行时系统就会重新启动一次消息发送的过程,否则,就会进行下一步,消息转发(Method Forwarding)。
  2. Fast Forwarding
    如果目标对象实现了- (id)forwardingTargetForSelector:(SEL)aSelector,Runtime这时就会调用这个方法,把这个消息转发给其他对象处理,只要这个方法的返回不是nil或self,整个消息发送的过程就会被重启,发送的对象就会变成返回的对象。否则,就会继续Normal Forwarding。
    这里叫Fast,是为了区别下一步的转发机制,因为这一步不会创建任何新的对象,但是下一步Normal Forwarding会创建一个NSInvocation对象,所以这一步相对快。
  3. Normal Forwarding
    这一步是runtime最后一次给开发者的挽救机会。
    首先,它会发送-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector方法签名:Objective-C对方法的参数个数、参数类型以及返回值类型的描述)
    消息获得函数的参数个数、参数类型和返回值类型。如果- methodSignatureForSelector:返回nil,runtime则会发出- (void)doesNotRecognizeSelector:(SEL)aSelector消息,程序这时也挂掉了。如果返回了一个函数签名,runtime就会创建一个NSInvocation对象并发送- forwardInvocation:消息给目标对象。

假设有方法签名为"@@:@",第一个@表示返回值类型为id,第二个@表示的是函数的调用者类型,第三个表示SEL,第四个@表示需要一个id类型的参数。
例子:
- (void)hello;对应的方法签名:v16@0:8,v16表示返回值类型为空,@0表示receiver(调用者)类型为id,:8表示SEL 方法标识。
- (id)hello:(id)x对应的方法签名:@24@0:8@16,@24表示返回值类型为id类型,@0表示receiver(调用者)类型为id,:8表示SEL方法标识,@16标识参数返回值类型为id类型。
-(void)hello:(id)x :(id)e对应的方法签名:v32@0:8@16@24,v32表示返回值类型为空,@0表示receiver(调用者)类型为id,:8表示SEL方法标识,@16和@24表示返回值参数为id类型。
总结:
v16,v32等表示返回类型为空,@16,@24,@32等表示返回值类型或参数类型为id类型,@0表示receiver类型为id,:8表示SEL方法标识。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容

  • 最近对经济学产生了兴趣,便开始日学之。 每每读到“万恶”的商人利用各种“伎俩”欺骗我们消费者的感情,便后背冒汗,两...
    凌易水阅读 569评论 0 3
  • 看目录,…海明威…加西亚马尔克斯!米兰昆德拉!…村上春树(其实我没看过他的书,很奇怪吧,我自己都觉得讶异)…就只知...
    I迎迎I阅读 224评论 0 0
  • 说到中国,相比起国外经常被提起的更加悠闲轻松的教育方式,国内刻苦的学习方法确实培养出了不少小有名气的聪明学生...
    Andy老师阅读 205评论 0 0
  • 今天跟人聊天中 每聊一个都没有成功 有时候觉得自己挺失败的 我确实是很不会跟人聊天 索性今天知道自己在哪里聊失败了...
    汐时阅读 104评论 0 0