快捷搜索:  as  xxx  xxx/a/toutiao/  抖个腿子  %27

关于一些 iOS面试问题的解答

1. 什么是 ARC? (ARC 是为了解决什么问题而诞生的?)

ARC 是 Automatic Reference Counting 的缩写, 即自动引用计数. 这是苹果在 iOS5 中引入的内存管理机制. Objective-C 和 Swift 使用 ARC 追踪和管理应用的内存使用. 这一机制使得开发者无需键入 retainrelease, 这不仅能够降低程序崩溃和内存泄露的风险, 而且可以减少开发者的工作量, 能够大幅度提升程序的流畅性和可预测性. 但是 ARC 不适用于 Core Foundation 框架中, 仍然需要手动管理内存.


2. 以下 keywords 有什么区别: assign vs weak, __block vs __weak

assignweak 是用于在声明属性时, 为属性指定内存管理的语义.

  • 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
  • __weakweak 的区别只在于, 前者用于变量的声明, 而后者用于属性的声明.

  • 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 中实现的.

    您可能还会对下面的文章感兴趣: