各位老铁们好,相信很多人对深度解析:编程工程师职业发展之路都不是特别的了解,因此呢,今天就来为大家分享下关于深度解析:编程工程师职业发展之路以及的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D% A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83% E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8 %B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD %94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#12-arc下没有显式指定属性关键字时默认的关键字是什么) 12、ARC下,当没有显式指定属性关键字时,默认关键字是什么?
基本数据类型对应的默认关键字为
原子、读写、分配
对于普通Objective-C 对象
原子、读写、强
参考链接:
Objective-C ARC: strong vs retain and weak vs assignVariable property attributes or Modifiers in iOS[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D% A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83% E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8 %B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD %94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#13-用属性声明的NSstring或nsarraynsdictionary经常使用copy关键字,为什么使用strong关键字。可能会导致什么问题?) 13. 用@property声明的NSString(或NSArray、NSDictionary)经常使用copy关键字,为什么?如果使用strong关键字会导致什么问题?
因为父类指针可以指向子类对象,所以使用copy的目的就是为了防止这个对象的属性受到外界的影响。使用copy时,无论是可变对象还是不可对象化对象,我持有的都是不可对象化对象。改了副本。
如果我们使用strong,那么这个属性可能指向一个可变对象。如果这个可变对象被外部修改,就会影响这个属性。
copy 这个特质所表达的所有权类似于强。然而,set方法并不保留新值,而是“复制”它。当属性类型为NSString 时,此特性通常用于保护封装,因为传递给setter 方法的新值可能指向NSMutableString 类的实例。该类是NSString 的子类,它表示一个可以修改其值的字符串。如果此时没有复制字符串,那么在设置属性之后,字符串的值可能会在对象不知情的情况下被更改。因此,此时就需要复制一个“不可变”的字符串,以保证对象中的字符串值不会在无意中发生改变。只要用于实现属性的对象是“可变的”,在设置新的属性值时就应该创建一个副本。
例子:
定义一个用strong修饰的数组:
@property (非原子,可读写,强) NSArray *array;
然后执行以下操作:
NSMutableArray *mutableArray=[[NSMutableArray alloc] init]; NSArray *array=@[ @1, @2, @3, @4 ]; self.array=mutableArray; [mutableArray 移除所有对象]; NSLog(@"%@",self.array); [mutableArray addObjectsFromArray:array]; self.array=[mutableArray 副本]; [mutableArray 移除所有对象]; NSLog(@"%@",self.array);
打印结果如下:
2015-09-27 19:10:32.523 CYLArrayCopyDmo[10681:713670] ()2015-09-27 19:10:32.524 CYLArrayCopyDmo[10681:713670] (1, 2, 3, 4)
(具体参见仓库附录中的Demo。)
为了理解这种方法,首先要知道有两种情况:
非集合对象上的复制和可变复制操作;
对集合类对象进行复制和mutableCopy 操作。
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D% A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83% E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8 %B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD %94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#1-非集合对象的复制操作) 1、非集合对象的复制操作:
在非集合对象中:不可变对象的复制操作是指针复制,mutableCopy操作是内容复制;对可变对象的copy 和mutableCopy 操作都是内容复制。代码简单表达如下:
[immutableObject copy] //浅拷贝
[immutableObject mutableCopy] //深拷贝
[mutableObject copy] //深拷贝
[mutableObject mutableCopy] //深拷贝
例如,以下代码:
NSMutableString *string=[NSMutableString stringWithString:@"origin"];//复制NSString *stringCopy=[字符串复制];
查看内存,会发现string和stringCopy的内存地址不同,说明此时进行的是内容复制和深复制。即使您执行以下操作:
[字符串appendString:@"origin!"]
stringCopy的值不会改变,但是如果不使用copy,stringCopy的值就会改变。集合对象可以用同样的方式推导。所以,
使用@property来声明NSString、NSArray和NSDictionary。 copy 关键字经常被使用,因为它们有相应的变量类型:NSMutableString、NSMutableArray 和NSMutableDictionary。它们之间可能存在赋值操作。为了确保对象中的字符串值不会无意中发生变化,在设置新的属性值时应进行复制。
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D% A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83% E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8 %B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD %94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#2集合类对象的复制和mutablecopy)2、集合类对象的复制和mutableCopy
集合类对象是指NSArray、NSDictionary、NSSet.等对象。我们首先看一个在集合不可变对象上使用copy 和mutableCopy 的示例:
NSArray *array=@[@[@"a", @"b"], @[@"c", @"d"]];NSArray *copyArray=[数组复制];NSMutableArray *mCopyArray=[数组mutableCopy] ;
查看内容可以发现copyArray和array的地址是相同的,但是mCopyArray和array的地址不同。注意,copy操作执行的是指针复制,而mutableCopy执行的是内容复制。但需要强调的是,这里的内容复制只是复制数组对象,数组集合内部的元素仍然是指针副本。这和上面非集合不可变对象的副本颇为相似,那么可变对象的副本也会类似吗?让我们继续看一个可变对象复制的示例:
NSMutableArray *array=[NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];NSArray *copyArray=[数组复制];NSMutableArray *mCopyArray=[数组mutableCopy];
看内存,正如我们所料,copyArray、mCopyArray和array的内存地址都是不同的,说明copyArray和mCopyArray都是复制array的内容。同样,我们可以得出结论:
在集合类对象中,复制不可变对象是指针复制,而mutableCopy是内容复制;复制和可变复制可变对象都是内容复制。但是:集合对象的内容副本仅限于对象本身,对象元素仍然是指针副本。代码简单表达如下:
[immutableObject copy] //浅复制[immutableObject mutableCopy] //单层深复制[mutableObject copy] //单层深复制[mutableObject mutableCopy] //单层深复制
这段代码的结论与非集合类的结论非常相似。
参考链接:iOS集合的深拷贝和浅拷贝
[
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D% A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83% E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8 %B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD %94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#14-合成实例变量的规则是什么?如果属性名为foo,则有一个属性名_foo。实例变量会自动合成新变量吗?) 14.用@synthesize合成实例变量的规则是什么?如果属性名为foo,则有一个名为_foo 的属性
实例变量,会自动合成新变量吗?
在回答之前,让我解释一下下一个概念:
实例变量=成员变量=ivar
这些表达方式可能被作者在下面使用,指的是同一件事。
正如苹果官方文档You Can Customize Synthesized Instance Variable Names所说:
在此输入图像描述
如果使用属性,编译器将自动编写访问属性所需的方法。这个过程称为“自动合成”。需要强调的是,这个过程是编译器在编译时执行的,因此这些“合成方法”的源代码在编辑器中是看不到的。除了生成方法代码之外,编译器还会自动为类添加适当类型的实例变量,并在属性名前面添加下划线作为实例变量的名称。
@interface CYLPerson : NSObject @property NSString *firstName; @property NSString *姓氏; @end 上面的例子中会生成两个实例变量,名字分别是_firstName
与_lastName。也可以在类的实现代码中传递@synthesize
指定实例变量名称的语法:
@implementation CYLPerson @synthesizefirstName=_myFirstName; @synthesize 姓氏=_myLastName; @结尾
上面的语法将命名生成的实例变量_myFirstName
与_myLastName
,而不是使用默认名称。一般情况下,不需要修改默认的实例变量名称,但是如果你不喜欢用下划线命名实例变量,可以使用此方法将其更改为你想要的名称。作者仍然建议使用默认的命名方案,因为如果每个人都遵守这个方案,那么每个人都可以理解所写的代码。
总结一下@synthesize合成实例变量的规则,有以下几点:
如果指定了成员变量的名称,则会生成具有指定名称的成员变量。
如果该成员已经存在,则不会再次生成。
如果@synthesize foo;
还会生成一个名为foo的成员变量,即:
如果不指定成员变量的名称,则会自动生成具有相同属性名称的成员变量。
如果@synthesize foo=_foo;
不会生成成员变量。
如果属性名为foo,则存在名为_foo 的属性
实例变量,会自动合成新变量吗?惯于。如下图:
在此处输入图像描述
[](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D %A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83 %E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0% E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7% AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#15-属性实例变量自动合成后synthesize还有哪些使用场景)15 。有了属性实例变量的自动合成之后,@synthesize还有哪些使用场景呢?
在回答这个问题之前,我们需要先明确一个问题:什么情况下不会进行autosynthesis(自动合成)?
当setter 和getter 都被重写时
当只读属性的getter 被覆盖时
当使用@dynamic时
@protocol 中定义的所有属性
类别中定义的所有属性
重载的属性
在子类中重写父类的属性时,必须使用@synthesize
手动合成ivar。
除了最后三项,其他的我们可以总结一个规则:当你想要手动管理@property的所有内容时,你会尝试实现@property的所有“访问器方法”(访问器方法)或者使用@ 动态的
为了达到这个目的,编译器会认为你打算手动管理@property,因此编译器会禁用autosynthesis(自动合成)。
因为autosynthesis(自动合成),大多数开发者已经习惯不手动定义ivar,而是依赖autosynthesis(自动合成)。但是一旦你需要使用ivar,而autosynthesis(自动合成)失败了,如果不是要手动定义ivar,那么你就得使用@synthesize
手动合成ivar。
实际上,@synthesize
该语法还有另外一种应用场景,但不建议大家使用:
可以在类的实现代码中传递@synthesize
指定实例变量名称的语法:
@implementation CYLPerson @synthesizefirstName=_myFirstName; @synthesize 姓氏=_myLastName; @结尾
上面的语法将命名生成的实例变量_myFirstName
与_myLastName
,而不是使用默认名称。一般情况下,不需要修改默认的实例变量名称,但是如果你不喜欢用下划线命名实例变量,可以使用此方法将其更改为你想要的名称。作者仍然建议使用默认的命名方案,因为如果每个人都遵守这个方案,那么每个人都可以理解所写的代码。
示例:应用场景:
////.m文件//http://weibo.com/luohanchenyilong/(微博@iOS程序犭元)//https://github.com/ChenYilong//打开第14、17行任意一行,编译成功@ import Foundation;@interface CYLObject : NSObject@property (非原子,复制) NSString *title;@end@implementation CYLObject { //NSString *_title;}//@synthesize title=_title;- (instancetype)init{ self=[super初始化]; if (self) { _title=@"微博@iOS程序犭元"; } return self;}- (NSString *)title { return _title;}- (void)setTitle:(NSString *)title { _title=[标题副本];}@end
结果编译器报错:
在此处输入图像描述
当你同时重写setter和getter时,系统不会生成ivar(实例变量/成员变量)。此时有两个选择:
或者如第14 行:手动创建ivar
或者如第17 行所示: use @synthesize foo=_foo;
,将@property 与ivar 关联。了解更多请点击-》When should I use @synthesize explicitly?【
](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D% A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83% E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8 %B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD %94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#16-如果向objc 中的nil 对象发送消息会发生什么) 16. 发送向objc 中的nil 对象发送消息当nil 对象发送消息时会发生什么?
在Objective-C 中向nil 发送消息是完全有效的——,但在运行时没有效果:
如果方法返回一个对象,则发送到nil 的消息将返回0 (nil)。例如:
人* motherInlaw=[[人配偶]母亲];
如果配偶对象为nil,那么mother发送给nil的消息也将返回nil。
如果方法返回值是指针类型,则其指针大小小于等于sizeof(void*)、float、dou
ble,long double 或者 long long 的整型标量,发送给 nil 的消息将返回0。 如果方法返回值为结构体,发送给 nil 的消息将返回0。结构体中各个字段的值将都是0。 如果方法的返回值不是上述提到的几种情况,那么发送给 nil 的消息的返回值将是未定义的。 具体原因如下: objc是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。 那么,为了方便理解这个内容,还是贴一个objc的源代码: // runtime.h(类在runtime中的定义)//http://weibo.com/luohanchenyilong///https://github.com/ChenYilongstructobjc_class { Class isa OBJC_ISA_AVAILABILITY; //isa指针指向Meta Class,因为Objc的类的本身也是一个Object,为了处理这个关系,runtime就创造了Meta Class,当给类发送[NSObject alloc]这样消息时,实际上是把这个消息发给了Class Object #if !OBJC2Class 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 OBJC2_UNAVAILABLE; // 方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在method Lists中遍历,如果cache了,常用的方法调用时就能够提高调用的效率。 struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表 #endif } OBJC2_UNAVAILABLE; objc在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实际所属的类,然后在该类中的方法列表以及其父类方法列表中寻找方法运行,然后在发送消息的时候,objc_msgSend方法不会返回值,所谓的返回内容都是具体调用时执行的。 那么,回到本题,如果向一个nil对象发送消息,首先在寻找对象的isa指针时就是0地址返回了,所以不会出现任何错误。 [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#17-objc中向一个对象发送消息obj-foo和objc_msgsend函数之间有什么关系)17. objc中向一个对象发送消息[obj foo]和objc_msgSend() 函数之间有什么关系? 具体原因同上题:该方法编译之后就是objc_msgSend() 函数调用. 我们用 clang 分析下,clang 提供一个命令,可以将Objective-C的源码改写成C++语言,借此可以研究下[obj foo]和objc_msgSend() 函数之间有什么关系。 以下面的代码为例,由于 clang 后的代码达到了10万多行,为了便于区分,添加了一个叫 iOSinit 方法, //// main.m//http://weibo.com/luohanchenyilong///https://github.com/ChenYilong//Copyright (c) 2015年 微博@iOS程序犭袁. All rights reserved.//#import "CYLTest.h"int main(int argc, char * argv[]) { @autoreleasepool { CYLTest *test = [[CYLTest alloc] init]; [test performSelector:(@selector(iOSinit))]; return 0; }} 在终端中输入 clang -rewrite-objc main.m 就可以生成一个main.cpp 的文件,在最低端(10万4千行左右)enter image description here 我们可以看到大概是这样的: ((void ()(id, SEL))(void )objc_msgSend)((id)obj, sel_registerName("foo"));也就是说: [obj foo];在objc动态编译时,会被转意为:objc_msgSend(obj, @selector(foo)); 。 [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#18-什么时候会报unrecognized-selector的异常)18. 什么时候会报unrecognized selector的异常? 简单来说: 当调用该对象上某个方法,而该对象上没有实现这个方法的时候, 可以通过“消息转发”进行解决。 简单的流程如下,在上一题中也提到过: objc是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。 objc在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实际所属的类,然后在该类中的方法列表以及其父类方法列表中寻找方法运行,如果,在最顶层的父类中依然找不到相应的方法时,程序在运行时会挂掉并抛出异常unrecognized selector sent to XXX 。但是在这之前,objc的运行时会给出三次拯救程序崩溃的机会: Method resolution objc运行时会调用+resolveInstanceMethod: 或者 +resolveClassMethod: ,让你有机会提供一个函数实现。如果你添加了函数,那运行时系统就会重新启动一次消息发送的过程,否则 ,运行时就会移到下一步,消息转发(Message Forwarding)。 Fast forwarding 如果目标对象实现了-forwardingTargetForSelector: ,Runtime 这时就会调用这个方法,给你把这个消息转发给其他对象的机会。 只要这个方法返回的不是nil和self,整个消息发送的过程就会被重启,当然发送的对象会变成你返回的那个对象。否则,就会继续Normal Fowarding。 这里叫Fast,只是为了区别下一步的转发机制。因为这一步不会创建任何新的对象,但下一步转发会创建一个NSInvocation对象,所以相对更快点。 Normal forwarding 这一步是Runtime最后一次给你挽救的机会。首先它会发送-methodSignatureForSelector: 消息获得函数的参数和返回值类型。如果-methodSignatureForSelector: 返回nil,Runtime则会发出-doesNotRecognizeSelector: 消息,程序这时也就挂掉了。如果返回了一个函数签名,Runtime就会创建一个NSInvocation对象并发送-forwardInvocation: 消息给目标对象。 为了能更清晰地理解这些方法的作用,git仓库里也给出了一个Demo,名称叫“ _objc_msgForward_demo ”,可运行起来看看。 [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#19-一个objc对象如何进行内存布局考虑有父类的情况)19. 一个objc对象如何进行内存布局?(考虑有父类的情况) 所有父类的成员变量和自己的成员变量都会存放在该对象所对应的存储空间中. 每一个对象内部都有一个isa指针,指向他的类对象,类对象中存放着本对象的 对象方法列表(对象能够接收的消息列表,保存在它所对应的类对象中) 成员变量的列表, 属性列表, 它内部也有一个isa指针指向元对象(meta class),元对象内部存放的是类方法列表,类对象内部还有一个superclass的指针,指向他的父类对象。 每个 Objective-C 对象都有相同的结构,如下图所示:enter image description here 翻译过来就是 Objective-C 对象的结构图ISA指针 根类的实例变量 倒数第二层父类的实例变量 ... 父类的实例变量 类的实例变量 根对象就是NSobject,它的superclass指针指向nil 类对象既然称为对象,那它也是一个实例。类对象中也有一个isa指针指向它的元类(meta class),即类对象是元类的实例。元类内部存放的是类方法列表,根元类的isa指针指向自己,superclass指针指向NSObject类。 如图:enter image description here [](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#20-一个objc对象的isa的指针指向什么有什么作用)20. 一个objc对象的isa的指针指向什么?有什么作用? 指向他的类对象,从而可以找到对象上的方法 [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#21-下面的代码输出什么)21. 下面的代码输出什么? @implementation Son : Father - (id)init { self = [super init]; if (self) { NSLog(@"%@", NSStringFromClass([self class])); NSLog(@"%@", NSStringFromClass([super class])); } return self; } @end答案:都输出 Son NSStringFromClass([self class]) = SonNSStringFromClass([super class]) = Son 这个题目主要是考察关于 Objective-C 中对 self 和 super 的理解。 我们都知道:self 是类的隐藏参数,指向当前调用方法的这个类的实例。那 super 呢? 很多人会想当然的认为“ super 和 self 类似,应该是指向父类的指针吧!”。这是很普遍的一个误区。其实 super 是一个 Magic Keyword, 它本质是一个编译器标示符,和 self 是指向的同一个消息接受者!他们两个的不同点在于:super 会告诉编译器,调用 class 这个方法时,要去父类的方法,而不是本类里的。 上面的例子不管调用[self class] 还是[super class] ,接受消息的对象都是当前 Son *xxx 这个对象。 当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用 super 时,则从父类的方法列表中开始找。然后调用父类的这个方法。 这也就是为什么说“不推荐在 init 方法中使用点语法”,如果想访问实例变量 iVar 应该使用下划线( _iVar ),而非点语法(self.iVar )。 点语法( self.iVar )的坏处就是子类有可能覆写 setter 。假设 Person 有一个子类叫 ChenPerson,这个子类专门表示那些姓“陈”的人。该子类可能会覆写 lastName 属性所对应的设置方法: //// ChenPerson.m// //// Created byhttps://github.com/ChenYilongon 15/8/30.// Copyright (c) 2015年http://weibo.com/luohanchenyilong/微博@iOS程序犭袁. All rights reserved.//#import "ChenPerson.h"@implementation ChenPerson@synthesize lastName = _lastName;- (instancetype)init{ self = [super init]; if (self) { NSLog(@"类名与方法名:%s(在第%d行),描述:%@",PRETTY_FUNCTION,LINE, NSStringFromClass([self class])); NSLog(@"类名与方法名:%s(在第%d行),描述:%@",PRETTY_FUNCTION,LINE, NSStringFromClass([super class])); } return self;}- (void)setLastName:(NSString*)lastName{ //设置方法一:如果setter采用是这种方式,就可能引起崩溃// if (![lastName isEqualToString:@"陈"])// {// [NSException raise:NSInvalidArgumentException format:@"姓不是陈"];// }// _lastName = lastName; //设置方法二:如果setter采用是这种方式,就可能引起崩溃 _lastName = @"陈"; NSLog(@"类名与方法名:%s(在第%d行),描述:%@",PRETTY_FUNCTION,LINE, @"会调用这个方法,想一下为什么?");}@end 在基类 Person 的默认初始化方法中,可能会将姓氏设为空字符串。此时若使用点语法( self.lastName )也即 setter 设置方法,那么调用将会是子类的设置方法,如果在刚刚的 setter 代码中采用设置方法一,那么就会抛出异常, 为了方便采用打印的方式展示,究竟发生了什么,我们使用设置方法二。 如果基类的代码是这样的: //// Person.m// nil对象调用点语法//// Created byhttps://github.com/ChenYilongon 15/8/29.// Copyright (c) 2015年http://weibo.com/luohanchenyilong/微博@iOS程序犭袁. All rights reserved.// #import "Person.h"@implementation Person- (instancetype)init{ self = [super init]; if (self) { self.lastName = @""; //NSLog(@"类名与方法名:%s(在第%d行),描述:%@",PRETTY_FUNCTION,LINE, NSStringFromClass([self class])); //NSLog(@"类名与方法名:%s(在第%d行),描述:%@",PRETTY_FUNCTION,LINE, self.lastName); } return self;}- (void)setLastName:(NSString*)lastName{ NSLog(@"类名与方法名:%s(在第%d行),描述:%@",PRETTY_FUNCTION,LINE, @"根本不会调用这个方法"); _lastName = @"炎黄";}@end 那么打印结果将会是这样的: 类名与方法名:-[ChenPerson setLastName:](在第36行),描述:会调用这个方法,想一下为什么? 类名与方法名:-[ChenPerson init](在第19行),描述:ChenPerson 类名与方法名:-[ChenPerson init](在第20行),描述:ChenPerson 我在仓库里也给出了一个相应的 Demo(名字叫:Demo_21题_下面的代码输出什么)。有兴趣可以跑起来看一下,主要看下他是怎么打印的,思考下为什么这么打印。 接下来让我们利用 runtime 的相关知识来验证一下 super 关键字的本质,使用clang重写命令: $ clang -rewrite-objc test.m 将这道题目中给出的代码被转化为: NSLog((NSString)&__NSConstantStringImpl__var_folders_gm_0jk35cwn1d3326x0061qym280000gn_T_main_a5cecc_mi_0, NSStringFromClass(((Class ()(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class")))); NSLog((NSString)&__NSConstantStringImpl__var_folders_gm_0jk35cwn1d3326x0061qym280000gn_T_main_a5cecc_mi_1, NSStringFromClass(((Class ()(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){ (id)self, (id)class_getSuperclass(objc_getClass("Son")) }, sel_registerName("class")))); 从上面的代码中,我们可以发现在调用 [self class] 时,会转化成 objc_msgSend 函数。看下函数定义: id objc_msgSend(id self, SEL op, ...) 我们把 self 做为第一个参数传递进去。 而在调用 [super class]时,会转化成 objc_msgSendSuper 函数。看下函数定义: id objc_msgSendSuper(struct objc_super *super, SEL op, ...) 第一个参数是 objc_super 这样一个结构体,其定义如下: struct objc_super { __unsafe_unretained id receiver; __unsafe_unretained Class super_class;}; 结构体有两个成员,第一个成员是 receiver, 类似于上面的 objc_msgSend 函数第一个参数self 。第二个成员是记录当前类的父类是什么。 所以,当调用 [self class] 时,实际先调用的是 objc_msgSend 函数,第一个参数是 Son当前的这个实例,然后在 Son 这个类里面去找 - (Class)class这个方法,没有,去父类 Father里找,也没有,最后在 NSObject类中发现这个方法。而 - (Class)class的实现就是返回self的类别,故上述输出结果为 Son。 objc Runtime开源代码对- (Class)class方法的实现: (Class)class { return object_getClass(self);}而当调用 [super class] 时,会转换成objc_msgSendSuper函数 。第一步先构造 objc_super 结构体,结构体第一个成员就是 self 。 第二个成员是 (id)class_getSuperclass(objc_getClass(“Son”)) , 实际该函数输出结果为 Father。 第二步是去 Father这个类里去找 - (Class)class ,没有,然后去NSObject类去找,找到了。最后内部是使用objc_msgSend(objc_super->receiver, @selector(class)) 去调用, 此时已经和[self class] 调用相同了,故上述输出结果仍然返回 Son。 参考链接:微博@Chun_iOS的博文刨根问底Objective-C Runtime(1)- Self & Super [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#22-runtime如何通过selector找到对应的imp地址分别考虑类方法和实例方法)22. runtime如何通过selector找到对应的IMP地址?(分别考虑类方法和实例方法) 每一个类对象中都一个方法列表,方法列表中记录着方法的名称,方法实现,以及参数类型,其实selector本质就是方法名称,通过这个方法名称就可以在方法列表中找到对应的方法实现. [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#23-使用runtime-associate方法关联的对象需要在主对象dealloc的时候释放么)23. 使用runtime Associate方法关联的对象,需要在主对象dealloc的时候释放么? 在ARC下不需要。 在MRC中,对于使用retain或copy策略的需要 。 在MRC下也不需要 无论在MRC下还是ARC下均不需要。2011年版本的Apple API 官方文档 - Associative References一节中有一个MRC环境下的例子: // 在MRC下,使用runtime Associate方法关联的对象,不需要在主对象dealloc的时候释放//http://weibo.com/luohanchenyilong/(微博@iOS程序犭袁)//https://github.com/ChenYilong//摘自2011年版本的Apple API 官方文档 - Associative References static char overviewKey;NSArray *array = [[NSArray alloc] initWithObjects:@"One", @"Two", @"Three", nil];// For the purposes of illustration, use initWithFormat: to ensure// the string can be deallocatedNSString *overview = [[NSString alloc] initWithFormat:@"%@", @"First three numbers"];objc_setAssociatedObject ( array, &overviewKey, overview, OBJC_ASSOCIATION_RETAIN);[overview release];// (1) overview valid[array release];// (2) overview invalid 文档指出 At point 1, the string overview is still valid because the OBJC_ASSOCIATION_RETAIN policy specifies that the array retains the associated object. When the array is deallocated, however (at point 2), overview is released and so in this case also deallocated. 我们可以看到,在[array release]; 之后,overview就会被release释放掉了。 既然会被销毁,那么具体在什么时间点? 根据WWDC 2011, Session 322 (第36分22秒)中发布的内存销毁时间表,被关联的对象在生命周期内要比对象本身释放的晚很多。它们会在被 NSObject -dealloc 调用的 object_dispose() 方法中释放。 对象的内存销毁时间表,分四个步骤: // 对象的内存销毁时间表//http://weibo.com/luohanchenyilong/(微博@iOS程序犭袁)//https://github.com/ChenYilong//根据 WWDC 2011, Session 322 (36分22秒)中发布的内存销毁时间表 1. 调用 -release :引用计数变为零 * 对象正在被销毁,生命周期即将结束. * 不能再有新的 __weak 弱引用, 否则将指向 nil. * 调用 [self dealloc] 2. 父类 调用 -dealloc * 继承关系中最底层的父类 在调用 -dealloc * 如果是 MRC 代码 则会手动释放实例变量们(iVars) * 继承关系中每一层的父类 都在调用 -dealloc 3. NSObject 调 -dealloc * 只做一件事:调用 Objective-C runtime 中的 object_dispose() 方法 4. 调用 object_dispose() * 为 C++ 的实例变量们(iVars)调用 destructors * 为 ARC 状态下的 实例变量们(iVars) 调用 -release * 解除所有使用 runtime Associate方法关联的对象 * 解除所有 __weak 引用 * 调用 free() 对象的内存销毁时间表:参考链接。 [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#24-objc中的类方法和实例方法有什么本质区别和联系)24. objc中的类方法和实例方法有什么本质区别和联系? 类方法: 类方法是属于类对象的 类方法只能通过类对象调用 类方法中的self是类对象 类方法可以调用其他的类方法 类方法中不能访问成员变量 类方法中不定直接调用对象方法 实例方法: 实例方法是属于实例对象的 实例方法只能通过实例对象调用 实例方法中的self是实例对象 实例方法中可以访问成员变量 实例方法中直接调用实例方法 实例方法中也可以调用类方法(通过类名) [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#下一篇文章将发布在这里会对以下问题进行总结并将本篇文章的勘误一并列出欢迎指正请持续关注微博ios程序犭袁)下一篇文章将发布在这里,会对以下问题进行总结,并将本篇文章的勘误一并列出,欢迎指正!请持续关注微博@iOS程序犭袁 @property部分主要参考Apple官方文档:Properties Encapsulate an Object’s Valuesruntime部分主要参考Apple官方文档:Declared Properties [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#25-_objc_msgforward函数是做什么的直接调用它将会发生什么)25. _objc_msgForward 函数是做什么的,直接调用它将会发生什么? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#26-runtime如何实现weak变量的自动置nil)26. runtime如何实现weak变量的自动置nil? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#27-能否向编译后得到的类中增加实例变量能否向运行时创建的类中添加实例变量为什么)27. 能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#28-runloop和线程有什么关系)28. runloop和线程有什么关系? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#29-runloop的mode作用是什么)29. runloop的mode作用是什么? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#30-以-scheduledtimerwithtimeinterval的方式触发的timer在滑动页面上的列表时timer会暂定回调为什么如何解决)30. 以+ scheduledTimerWithTimeInterval...的方式触发的timer,在滑动页面上的列表时,timer会暂定回调,为什么?如何解决? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#31-猜想runloop内部是如何实现的)31. 猜想runloop内部是如何实现的? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#32-objc使用什么机制管理对象内存)32. objc使用什么机制管理对象内存? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#33-arc通过什么方式帮助开发者管理内存)33. ARC通过什么方式帮助开发者管理内存? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#34-不手动指定autoreleasepool的前提下一个autorealese对象在什么时刻释放比如在一个vc的viewdidload中创建)34. 不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建) [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#35-bad_access在什么情况下出现)35. BAD_ACCESS 在什么情况下出现? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#36-苹果是如何实现autoreleasepool的)36. 苹果是如何实现autoreleasepool的? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#37-使用block时什么情况会发生引用循环如何解决)37. 使用block时什么情况会发生引用循环,如何解决? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#38-在block内如何修改block外部变量)38. 在block内如何修改block外部变量? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#39-使用系统的某些block-api如uiview的block版本写动画时是否也考虑引用循环问题)39. 使用系统的某些block api(如UIView的block版本写动画时),是否也考虑引用循环问题? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#40-gcd的队列dispatch_queue_t分哪两种类型)40. GCD的队列(dispatch_queue_t )分哪两种类型? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#41-如何用gcd同步若干个异步调用如根据若干个url异步加载多张图片然后在都下载完成后合成一张整图)41. 如何用GCD同步若干个异步调用?(如根据若干个url异步加载多张图片,然后在都下载完成后合成一张整图) [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#42-dispatch_barrier_async的作用是什么)42. dispatch_barrier_async 的作用是什么? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#43-苹果为什么要废弃dispatch_get_current_queue)43. 苹果为什么要废弃dispatch_get_current_queue ? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#44-以下代码运行结果如何)44. 以下代码运行结果如何? (void)viewDidLoad{ [super viewDidLoad]; NSLog(@"1"); dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"2"); }); NSLog(@"3");}[ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#45-addobserverforkeypathoptionscontext各个参数的作用分别是什么observer中需要实现哪个方法才能获得kvo回调)45. addObserver:forKeyPath:options:context:各个参数的作用分别是什么,observer中需要实现哪个方法才能获得KVO回调? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#46-如何手动触发一个value的kvo)46. 如何手动触发一个value的KVO [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#47-若一个类有实例变量nsstring-_foo调用setvalueforkey时可以以foo还是_foo作为key)47. 若一个类有实例变量NSString *_foo ,调用setValue:forKey:时,可以以foo还是_foo 作为key? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#48-kvc的keypath中的集合运算符如何使用)48. KVC的keyPath中的集合运算符如何使用? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#49-kvc和kvo的keypath一定是属性么)49. KVC和KVO的keyPath一定是属性么? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#50-如何关闭默认的kvo的默认实现并进入自定义的kvo实现)50. 如何关闭默认的KVO的默认实现,并进入自定义的KVO实现? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#51-apple用什么方式实现对一个对象的kvo)51. apple用什么方式实现对一个对象的KVO? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#52-iboutlet连出来的视图属性为什么可以被设置成weak)52. IBOutlet连出来的视图属性为什么可以被设置成weak? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#53-ib中user-defined-runtime-attributes如何使用)53. IB中User Defined Runtime Attributes如何使用? [ ](https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md#54-如何调试bad_access错误)54. 如何调试BAD_ACCESS 错误 [【深度解析:编程工程师职业发展之路】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
我感觉程序猿总是充满活力,代码写的像诗一样优美。
有20位网友表示赞同!
这种工作真酷啊,需要不断学习新技术,永远在挑战自我。
有6位网友表示赞同!
听说很多程序员都是内向型的人格,他们更喜欢自己静静地写代码。
有19位网友表示赞同!
这篇文章让我对程序猿的工作有了更深的了解,挺想尝试一下编程的兴趣。
有13位网友表示赞同!
程序猿的生活模式真独特,经常熬夜加班吧。
有20位网友表示赞同!
最近也开始学编程了,感觉确实需要很好的逻辑思维能力。
有6位网友表示赞同!
希望将来我也能成为一个厉害的程序员!
有6位网友表示赞同!
程序猿的世界真是充满神秘感啊,各种代码和算法,我听不太懂哈哈。
有11位网友表示赞同!
不知道这个文章里写的程序猿的故事是真实的还是虚构的?
有10位网友表示赞同!
我朋友是程序猿,他经常给我讲关于代码的有趣的事例。
有14位网友表示赞同!
程序猿需要非常强的抗压能力,经常要面对各种bug和deadline。
有17位网友表示赞同!
这篇文章让我对编程这个行业有了更多的兴趣!
有11位网友表示赞同!
我猜程序员应该很享受自由的工作环境吧,自己敲自己的代码。
有15位网友表示赞同!
最近流行有很多关于程序猿的影视作品,看来很多人都在关注这个群体啊。
有19位网友表示赞同!
不知道现在的程序猿们都喜欢玩什么游戏?
有11位网友表示赞同!
感觉程序员是一个非常有成就感的工作吧,能够创造出软件来帮助人们生活。
有19位网友表示赞同!
这个标题让我联想到很多关于程序员的网络段子,哈哈!
有17位网友表示赞同!
看完这个标题我已经迫不及待想要读整篇文章了!
有5位网友表示赞同!