1 向 nil 发送消息会发生什么,为什么不会 crash
nil 的定义是一个空指针,是 oc 对象的字面值0;
oc 调用方法其实是发消息,通过 objc_msgSend来发送消息,这个方法会判断 self,当 self 为空的时候,直接返回。所以不会 crash。
2 nil Nil NSNull 区别
nil 是类对象赋值(id 类型)
Nil 是类指针赋值
NULL 任何指针赋值
NSNull 是一个类对象,包含了一个方法 +(NSNull *)null;
3 id
objc任何对象都是 id 类型
4 __block __weak区别
__bolck在 ARC 和 MRC 下都可以使用,可以修饰对象,也可以修饰基本数据类型
__weak只能在 ARC 下使用,只能修饰对象不能修饰基本数据类型
__block修饰变量可以使变量在 Block 中被改变,而__weak不可以
__weak在 ARC 环境中避免循环引用的__block在 ARC 环境中可能会造成循环引用
可以手动在 block 底部去将__block修饰的变量置为空避免循环引用。在非 arc 环境下__block 是可以避免循环引用的
5 堆和栈的区别
oc 对象分配在堆中,内存需要自己手动释放
非 oc 对象分配在栈中,不需要手动管理内存
堆是动态分配和回收的
栈可动态分配也可以静态分配,动态分配也是系统管理内存
6 class 方法和 instance 方法的区别是什么
class 方法是类方法只能调用类方法,不能调用实例方法
class 方法可以通过创建对象来调用实例方法
class 方法不能使用实例变量可以使用 self
类对象里的 self 是class
实例方法里的 self 是对象的首地址
类方法是+开头,实例方法是-开头
7 autorelease 和 release 的区别
autorelease 其实是先创建一个 autoreleasepool,在这个 autoreleasepool 中创建对象,然后调用 autorelease 方法,标记为 pool 释放的对象。
每一个 NSRunLoop 都对应一个 autoreleasepool,当 runloop 结束时,会调用相对用的 autoreleasepool
8 autoreleasepool 如何工作
手动添加 autoreleasepool
1 编写的程序不是基于 UI 框架的
2 编写的 循环中创建了大量的临时变量
3 创建了一个辅助线程
当创建一个 autoreleasepool 实际上是调用了 objc_autoreleasePoolPush()函数,向堆栈内压入一个自动释放池,执行完一个方法后调用objc_autoreleasePoolPop()自动释放自动释放池
hotpage 当前正在使用的page
再往下其实是调用 C++类的AutoReleasePapge的push 和 pop 方法,AutoReleasePoolPage是一个双向列表大小为4096Bytes
9 pushViewController 和 presentViewController 的区别
push 是在 navigation 栈里操作的,而 present 是没有 navagation 的
persent 可以在任何控制器上启动一个新的页面
push 是从右向左显示
present 是从下向上显示
10 __weak __strong
如果一个对象不用__weak修饰而直接被 block 引用,那么这个对象在 block 定义的时候,引用计数就会被加1,一般 block 定义在栈上,但是当 block 被复制到堆上的时候引用计数又会加1,其实相当于一般情况下加了两次,但是用 __weak修饰之后,引用对象计数不会加。当时当对象在外面释放掉的时候会导致 block 里面无法访问到该对象,所以此时就可以在 block 内部使用__strong强引用一次,在内部使用__strong,只有在 block 运行的时候才会引用计数+1,但是当运行结束之后也是会-1的