没有合适的资源?快使用搜索试试~ 我知道了~
1. 什么是 ARC 4. 使用 nonatomic 一定是线程安全的吗 5. 描述一个你遇到过的 retain cycle 例子. 7. 为什么其他语言里叫函
资源详情
资源评论
资源推荐
HOME ! SUBSCRIBE
"
关于一些 iOS 面试问题的
解答
2015年04月26日
这篇 post 主要是对知乎上 iOS程序员的问题列表 的回答, 也算是对自
己已有的知识进行整理.
如果你对本篇 post 中的回答有所疑问, 可以在下面留言. 如果有问题,
我一定会修改的 :-)
问题以及回答
1. 什么是 ARC? (ARC 是为了解决什么问
题而诞生的?)
ARC 是 Automatic Reference Counting 的缩写, 即自动引用计数. 这是
苹果在 iOS5 中引入的内存管理机制. Objective-C 和 Swift 使用 ARC
追踪和管理应用的内存使用. 这一机制使得开发者无需键入 retain 和
release , 这不仅能够降低程序崩溃和内存泄露的风险, 而且可以减少开
发者的工作量, 能够大幅度提升程序的流畅性和可预测性. 但是 ARC 不
适用于 Core Foundation 框架中, 仍然需要手动管理内存.
2. 以下 keywords 有什么区别: assign vs
weak , __block vs __weak
assign 和 weak 是用于在声明属性时, 为属性指定内存管理的语义.
assign 用于简单的赋值, 不改变属性的引用计数, 用于 Objective-C
中的 NSInteger , CGFloat 以及 C 语言中 int , float , double 等数据
类型.
weak 用于对象类型, 由于 weak 同样不改变对象的引用计数且不持
有对象实例, 当该对象废弃时, 该弱引用自动失效并且被赋值为
nil , 所以它可以用于避免两个强引用产生的循环引用导致内存无
法释放的问题.
__block 和 __weak 之间的却是确实极大的, 不过它们都用于修饰变量.
前者用于指明当前声明的变量在被 block 捕获之后, 可以在 block
中改变变量的值. 因为在 block 声明的同时会截获该 block 所使用
的全部自动变量的值, 而这些值只在 block 中只具有"使用权"而不
具有"修改权". 而 __block 说明符就为 block 提供了变量的修改权.
后者是所有权修饰符, 什么是所有权修饰符? 这里涉及到另一个问
题, 因为在 ARC 有效时, id 类型和对象类型同 C 语言中的其他类型
不同, 必须附加所有权修饰符. 所有权修饰符一种有 4 种:
__strong
__weak
__unsafe_unretained
__autorelease
__weak 与 weak 的区别只在于, 前者用于变量的声明, 而后者用于属
性的声明.
3. __block 在 ARC 和非 ARC 下含义一样
吗?
__block 在 ARC 下捕获的变量会被 block retain, 这样可能导致循环
引用, 所以必须要使用弱引用才能解决该问题. 而在非 ARC 下, 可以直
接使用 __block 说明符修饰变量, 因为在非 ARC 下, block 不会 retain
捕获的变量.
4. 使用 nonatomic 一定是线程安全的吗?
nonatomic 的内存管理语义是非原子的, 非原子的操作本来就是线程不
安全的, 而 atomic 的操作是原子的, 但是并不意味着它是线程安全的,
它会增加正确的几率, 能够更好的避免线程的错误, 但是它仍然是线程
不安全的.
当使用 nonatomic 的时候, 属性的 setter 和 getter 操作是非原子的, 所
以当多个线程同时对某一属性进行读和写的操作, 属性的最终结果是不
能预测的.
当使用 atomic 时, 虽然对属性的读和写是原子的, 但是仍然可能出现线
程错误: 当线程 A 进行写操作, 这时其他线程的读或写操作会因为该操
作的进行而等待. 当 A 线程的写操作结束后, B 线程进行写操作, 然后
当 A 线程进行读操作时, 却获得了在 B 线程中的值, 这就破坏了线程安
全, 如果有线程 C 在 A 线程读操作前 release 了该属性, 那么还会导致
程序崩溃. 所以仅仅使用 atomic 并不会使得线程安全, 我们还需要为线
程添加 lock 来确保线程的安全.
atomic 都不是一定线程安全的, nonatomic 就更不必多说了.
5. 描述一个你遇到过的 retain cycle 例子.
6. + (void)load; 和 + (void)initialize; 有
什么用处?
当类对象被引入项目时, runtime 会向每一个类对象发送 load 消息.
load 方法还是非常的神奇的, 因为它会在每一个类甚至分类被引入时
仅调用一次, 调用的顺序是父类优先于子类, 子类优先于分类. 而且
load 方法不会被类自动继承, 每一个类中的 load 方法都不需要像
viewDidLoad 方法一样调用父类的方法. 由于 load 方法会在类被 import
时调用一次, 而这时往往是改变类的行为的最佳时机. 我在
DKNightVersion 中使用 method swizlling 来修改原有的方法时, 就是在
分类 load 中实现的.
initialize 方法和 load 方法有一些不同, 它虽然也会在整个 runtime
过程中调用一次, 但是它是在该类的第一个方法执行之前调用, 也就是
说 initialize 的调用是惰性的, 它的实现也与我们在平时使用的惰性初
始化属性时基本相同. 我在实际的项目中并没有遇到过必须使用这个方
法的情况, 在该方法中主要做静态变量的设置并用于确保在实例初始化
前某些条件必须满足.
7. 为什么其他语言里叫函数调用,
Objective-C 中是给对象发送消息 (谈下对
剩余15页未读,继续阅读
点墨楼
- 粉丝: 32
- 资源: 281
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0