美文网首页
iOS面试题-OC

iOS面试题-OC

作者: CyrusCao | 来源:发表于2017-03-21 09:23 被阅读24次

    1. 如何手动触发一个value的KVO


    NSObject 有 willChangeValueForKey:didChangevlueForKey: 两个方法,会在 KVO 的时候调用,我们可以手动重写这两个方法。

    2. @protocol 和 category 中使用 @property


    • 在协议中添加属性,只会生成accessor,并没有后为遵循协议的对象添加属性。
    • 分类中也是这样
    • 如果真的需要添加属性,可以用 runtime 方法:objc_setAssociatedObjectobjc_getAssociatedObject

    3. Runtime


    在类中向使用 runtime ,需要先导入<objc/message.h>。

    消息机制

    objc_msgSend(objc_getClass(“Person”), sel_registerName(“doSth”));
    
    // 或者第一个参数是一个对象:
    objc_msgSend(obj, sel_registerName(“doSth”));
    
    // 也可以调用带参数的方法:
    objc_msgSend(obj, sel_registerName(@selector(eat:),”food”));
    
    // 注意这里参数和方法名之间是逗号关系
    

    交换方法(method swizzing)

    我们在类的 load 方法中进行方法的交换:

    + (void)load
    {
      // 获得两个将要交换的方法
      Method oldMethod = class_getClassMethod(self, @selector(oldMethod:));
      Method newMethod = class_getClassMethod(self, @selector(newMethod:));
      // 交换:
      method_exchangeImplamentations(oldMethod, newMethod);
    }
    

    动态添加方法

    会员机制、收费机制、部分受限制功能,这些都需要动态添加方法来实现。

    只要对象调用了一个未实现的方法,就会调用 resolveInstanceMethod: 方法,所以我们可以在这个方法中进行添加:

    class_addMethod(类,sel,方法名,类型);
    

    动态添加属性

    扩展属性只会生成 accessor 方法,不能在类中访问添加的成员变量,所以我们可以使用 runtime 添加属性:

    objc_setAssociatedObject(对象, 属性名称, 属性值, 枚举策略);
    

    访问这个动态添加的属性:

    objc_getAssociatedObject(对象, 属性名);
    

    为类添加属性的过程,实际上就是把属性和类关联起来,达到同生共死的目的。

    消息转发

    _objc_msgForward
    

    4. 方法调用流程


    • 通过 isa 指针找到类对象或元类的方法列表
    • 注册方法编号
    • 根据方法编号找到对相应的方法的地址(SEL)
    • 在代码段中找到方法的具体实现(IMP)

    5. 引用和指针的区别


    • 引用是指针的一种别称
    • 引用不能为空,指针可以
    • 引用初始化后不可改变,指针可以

    6. 标准宏


    #define Min(a,b) (((a)>=(b))?(b):(a))
    

    由于是原样替换,所以要加上括号

    7. 自定义对象实现copy


    • 使自定义对象遵循 NSCopy 协议
    • 重写父类的 copyWithZone 方法
      • 创建一个新对象
      • 设置当前对象的值给新对象
      • 返回新的对象
    - (id) copyWithZone:(NSZone *)zone
    {
      Person *p = [[[self class] allocWithZone] init];
      p.age = _age;
      p.name= _name;
      return p;
    }
    

    8. @class 和 #import 以及 @import


    • import 确保该头文件只被导入一次,无论在该文件中出现几次。
    • @class 告诉编译器,无需知道类的具体实现,只需要知道是个类就好了。这样可以避免类之间的依赖关系导致的重复编译。
      OC 中的对象都是动态分配内存,所以在编译时,编译器不需要了解这个对象的具体的内容,只需要获取指向这个对象的指针就可以了。这也回答了为什么 @class 关键字只会出现在 @interface 而不能出现在 @implementation 中。
    • @import 可以让你只引用一个库里的某一个类。

    9. +load 和 +initialize 的区别是什么?


    • load 只要类所在文件被引用就会被调用
    • initialize 是在类或者其子类的第一个方法被调用前调用

    所以如果类没有被引用进项目,就不会有load调用;但即使类文件被引用进来,但是没有使用,那么 initialize 也不会被调用。

    10. 各种修饰符的特点以及使用场合


    • retainstrongretain 是 MRC 下的 strong
    • assignweakassign 是MRC下的 weakweak 必须作用于 oc 对象,而 assign 不必。weak 在作用对象销毁后直接将指针置为 nil。而 assign 会让属性的 setter 方法直接传递值,不考虑内存管理,所以通常用于基本数据类型。
    • `copy:对不可变对象使用时,可以防止外界的对实例变量的误改。

    11. new、alloc/init 的区别


    new 相当于一种快捷省事版的 alloc/init,其本质都是开辟内存空间并且初始化对象。但 alloc/init 在内部会使用一个 zone 机制,将相关的对象分配在相邻的内存中,以便检索对象时减少损耗。并且 new 无法在创建对象时给定参数。

    12. 深复制与浅复制


    • [immutableObject copy] 浅复制
    • [immutableObject mutableCopy] 深复制
    • [mutableObject copy] 深复制
    • [mutableObject mutableCopy] 深复制

    13. runtime 中,SEL 和 IMP 的区别


    SEL只是方法编号,IMP(implementation) 是方法具体的地址。

    14. 为什么 Extension 可以增加实例变量, 而 Category 不可以?


    • Extension: 在编译期进行,与类同生共死。
    • Category: 在运行期进行。

    Category 在运行期间进行,但类在内存中的布局已经成型,添加实例变量会危险的修改类的结构。

    15. __block__weak修饰符的区别


    • __block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。
    • __weak只能在ARC模式下使用,也只能修饰对象,不能修饰基本数据类型(int)。
    • __block对象可以在block中被重新赋值,而__weak不可以。

    16. isMemberOfClass 和 isKindOfClass 的异同


    两者都能检测一个对象是否是某个类的成员,但后者还可以检测一个对象是否为某个类的后代,而前者却不行。

    17. 谈谈instancetype和id的异同


    • 相同点
      都可以作为方法的返回类型

    • 不同点
      ①instancetype可以返回和方法所在类相同类型的对象,id只能返回未知类型的对象;
      ②instancetype只能作为返回值,不能像id那样作为参数

    18. atomic和nonatomic的区别,默认是哪个?


    • atomic 是默认的,原子属性,防止多线程下的不安全
    • nonatomic 是可以添加的,如果是不用考虑多线程安全的话,可以用这个属性防止编译器生成过多的代码。

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


    什么都不会发生。

    objc是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。

    20. 如何访问并修改一个类的私有属性?


    • 通过 KVC 可以访问一个类的私有属性
    • 通过 runtime 可以修改

    21. accessibility 访问限制修饰符


    • @private:当前类
    • @protected:当前类以及子类
    • @package:不同包时是 private,同包使用时是public
    • @public:当前类以及其他类

    22. 如何序列化自定义对象?


    实现 NSCoding 协议。

    23. 如何调试BAD_ACCESS错误?


    Xcode 7 已经集成了BAD_ACCESS捕获功能:Address Sanitizer

    24. 数据持久化方式以及使用场景


    • plist 文件 键值对存储,有嵌套关系。比如城市名称
    • preference(UserDefaults)轻量数据。比如偏好设置
    • SQLite 重量数据。比如视频
    • CoreData sqlite的封装。
    • NSKeyedAchiver 序列化自定义对象

    25. 应用程序沙盒的目录结构


    沙盒机制使应用之间不能互相访问数据

    屏幕快照 2017-01-29 下午4.51.52.png

    Documents

    将应用程序的数据文件保存在该目录下.不过这些数据类型仅限于不可以再生的数据,可再生的数据文件应该存在LIbrary/Cache下

    Library 它有两个子文件

    • caches 主要是缓存文件,用户使用过程中缓存都可以保存在这些目录中.保存那些可再生的文件,比如网络数据请求.因此,应用程序通常还需要负责删除这些文件.
    • Preferences 应用程序的偏好设置文件. 我们使用NSUserDefaults写的设置数据都会保存到该目录下的一个plist文件中 它会被iTunes同步

    tmp

    各种临时文件, 保存应用再次启动时不需要的文件.而且,当应用不在需要这些文件时应主动将其删除,因为该目录下的东西随时有可能被系统清除,目前已知的一种可能清理的原因是系统磁盘存储空间不足的时候

    相关文章

      网友评论

          本文标题:iOS面试题-OC

          本文链接:https://www.haomeiwen.com/subject/jkysjttx.html