2018年iOS面试题runtime

作者: 爱恨的潮汐 | 来源:发表于2018-04-11 22:44 被阅读53次

    1、什么情况使用 weak 关键字,相比 assign 有什么不同?
    什么情况使用 weak 关键字?
    在 ARC 中,在有可能出现循环引用的时候,往往要通过让其中一端使用 weak 来解决,比如: delegate 代理属性
    自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用 weak,自定义 IBOutlet 控件属性一般也使用 weak;当然,也可以使用strong。在下文也有论述:《IBOutlet连出来的视图属性为什么可以被设置成weak?》
    不同点:
    weak 此特质表明该属性定义了一种“非拥有关系” (nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同assign类似, 然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。 而 assign 的“设置方法”只会执行针对“纯量类型” (scalar type,例如 CGFloat 或 NSlnteger 等)的简单赋值操作。
    assign 可以用非 OC 对象,而 weak 必须用于 OC 对象

    2、@property中有哪些属性关键字?/ @property 后面可以有哪些修饰符?
    答案:属性可以拥有的特质分为四类:

    (1)原子性---nonatomic特性

    在默认情况下,由编译器合成的方法会通过锁定机制确保其原子性(atomicity)。如果属性具备nonatomic性质,则不使用同步锁。请注意,尽管没有名为“atomic”的特性(如果某属性不具备nonatomic),但是仍然可以在属性特质中写明这一点,编译器不会报错。若是自己定定义存取方法,那么就该遵从与属性特质相符的原子特性。

    (2)读/写权限 --- readwrite(读写)、readonly(只读)

    (3)内存管理语义 --- assign、strong、weak、unsafe_unretained、copy

    (4)方法名 --- getter=<name>、setter=<name>

    getter=<name>的 样式:

    @property(nonatomic,getter = isOn) BOOL on;
    setter = <name>一般用在特殊的情境下,比如:在数据反序列化、转模型的过程中,服务器返回的字段如果以init开头,所以你需要定义一个init开头的属性,但默认生成setter与getter方法也会init开头,而编译器会吧所有以init开头的方法当成初始化方法,而初始化方法只能返回self类型,因此编译器会报错;
    这时你就可以使用下面的方式来避免编译器报错:

    @property(nonatomic,strong,getter = p_initBy,setter = setP_initBy:)NSStirng *initBy;
    另外也可以用关键字进行特殊说明,来避免编译器错误:

    @property (nonatomic, readwrite, copy, null_resettable) NSString *initBy;

    • (NSString *)initBy__attribute__((objc_method_family(none)));
      不常用的:no nnull, null_resettable, nullable

    3、 _objc_msgForward函数是做什么的?直接调用它将会发生什么?
    答案:_objc_msgForward是IMP类型,用于消息转发的:当向一个对象发送一条消息,但它并没有实现的时候,_objc_msgForward会尝试做消息转发
    直接调用_objc_msgForward是非常危险
    的事,这是把双刃刀,如果用不好会直接导致程序Crash,但是如果用得好,能做很多非常酷的事。

    4、能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?
    答案:不能向编译后得到的类中增加实例变量;能向运行时创建的类中添加实例变量;
    分析如下:
    (1)因为编译后的类已经注册在runtime中,类结构体中的objc_ivar_list 实例变量的链表和instance_size实例变量的内存大小已经确定,同时runtime 会调用class_setIvarLayout 或 class_setWeakIvarLayout来处理strong weak引用,所以不能向存在的类中添加实例变量
    (2)运行时创建的类是可以添加实例变量,调用 class_addIvar函数,但是得在调用objc_allocateClassPair之后,objc_registerClassPair之前,原因同上。

    5、runtime如何实现weak变量的自动置nil?
    答案:runtime 对注册的类, 会进行布局,对于 weak 对象会放入一个 hash 表中。 用 weak 指向的对象内存地址作为 key,当此对象的引用计数为0的时候会 dealloc,假如 weak 指向的对象内存地址是a,那么就会以a为键, 在这个 weak 表中搜索,找到所有以a为键的 weak 对象,从而设置为 nil。

    6、runloop的mode作用是什么?
    答案:model 主要是用来指定事件在运行循环中的优先级的,分为:

    NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态
    UITrackingRunLoopMode:ScrollView滑动时
    UIInitializationRunLoopMode:启动时
    NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合
    苹果公开提供的 Mode 有两个:

    NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
    NSRunLoopCommonModes(kCFRunLoopCommonModes)

    7、BAD_ACCESS在什么情况下出现?
    访问了悬垂指针,比如对一个已经释放的对象执行了release、访问已经释放对象的成员变量或者发消息。 死循环。

    8、KVC的keyPath中的集合运算符如何使用?
    必须用在集合对象上或普通对象的集合属性上
    简单集合运算符有@avg, @count , @max , @min ,@sum,
    格式 @"@sum.age"或 @"集合属性.@max.age"

    9、lldb(gdb)常用的调试命令?
    答案:breakpoint 设置断点定位到某一个函数
    n 断点指针下一步
    po打印对象

    10、GCD的队列(dispatch_queue_t)分哪两种类型?
    串行队列Serial Dispatch Queue
    并行队列Concurrent Dispatch Queue

    相关文章

      网友评论

      本文标题:2018年iOS面试题runtime

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