2018年iOS面试题runtime

1、什么情况使用 weak 关键字,相比 assign 有什么不同?

(1)什么情况使用 weak 关键字?

在 ARC 中,在有可能出现循环引用的时候,往往要通过让其中一端使用 weak 来解决,比如: delegate 代理属性
自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用 weak,自定义 IBOutlet 控件属性一般也使用 weak;当然,也可以使用strong。在下文也有论述:《IBOutlet连出来的视图属性为什么可以被设置成weak?》

(2)不同点:

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=、setter=
getter=的 样式:

@property(nonatomic,getter = isOn) BOOL on;
setter = 一般用在特殊的情境下,比如:在数据反序列化、转模型的过程中,服务器返回的字段如果以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"或 @"集合属性[email protected]"

9、lldb(gdb)常用的调试命令?

答案:breakpoint 设置断点定位到某一个函数
n 断点指针下一步
po打印对象

10、GCD的队列(dispatch_queue_t)分哪两种类型?

串行队列Serial Dispatch Queue
并行队列Concurrent Dispatch Queue

你可能感兴趣的:(2018年iOS面试题runtime)