iOS 常见面试问题二

157 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

请简述信号量和调度组的原理

信号量 作用一般是用来使任务同步执行,类似于互斥锁,用户可以根据需要控制GCD的最大并发数!\

  • 1.创建信号量,并控制通行的额值dispatch_semaphore_t sem = dispatch_semaphore_create(1);\
  • 2.dispatch_semaphore_wait底层源码中是一个原有信号量 -1 的和一个操作,当我们信号量小于0的时候会进入判断等待的时间,如果设定为DISPATCH_TIME_FOREVER就进入do-while死循环,等待信号发起\
  • 3.dispatch_semaphore_signal原理\
    • 里面os_atomic_inc2o原子操作自增加1,然后会判断,如果value > 0,就会返回0.
    • 例如value加1之后还是小于0,说明是一个负数,也就是调用dispatch_semaphore_wait次数太多了,加一次后依然小于0,并且 == LONG_MIN 就报异常Unbalanced call to dispatch_semaphore_signal()
    • 然后会调用_dispatch_semaphore_signal_slow方法的,做容错处理,_dispatch_sema4_signal是一个 do while循环调用semaphore_signal,这样就能响应dispatch_semaphore_wait陷入的死循环等待

调度组 \

  • 1.dispatch_group_create创建组控制所有调度组的状态
  • 2.进组和出组
    • dispatch_group_enter:调度组 value-1 等待信号
    • dispatch_group_enterold_value == DISPATCH_GROUP_VALUE_MAX 证明Too many nested calls to dispatch_group_enter()也会报错
    • dispatch_group_leave:调度组 value+1 达到最开始设定的值就会调用_dispatch_group_wake去唤醒dispatch_group_enter堵塞的状态进而去执行_dispatch_continuation_async 进而执行任务
    • dispatch_group_leave +1 还是value=0 证明进组和出组不匹配
  • 3.dispatch_group_async进组任务封装了dispatch_group_enter进组 +dispatch_group_leave出组
  • 4.dispatch_group_notify:当old_state == 0的时候调用_dispatch_group_wake,也就是调用block的callout。与leave调用了同一个方法,其实起到一个监听同志执行的效果。
KVO的底层原理机制分析

我们可以大致的分析一下就可以,抓住重点,不需要长篇大论。
比如:KVO是基于runtime机制实现的,KVO运用了isa-swizzling技术,isa-swizzling就是类型混合指针机制,将2个对象的isa指针互相调换,就是俗称的黑魔法。\

  • 当某个类的属性对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类:NSKVONtifying_xxx,在这个派生类中重写基类中任何观察属性的setter方法。派生类在被重写的setter方法内实现真正的通知机制。例如如果原类为LGPerson,那么生成的派生类名为NSKVONotifying_LGPerson
  • 每个类对象中都有一个isa指针指向当前类,当一个类对象的第一次被观察,那么系统会偷偷将isa指针指向动态生成的派生类,从而在给被监控属性赋值时执行的是派生类的setter方法
  • 键值观察通知依赖于NSObject的两个方法:willChangeValueForKey:didChangeValueForKey:在一个被观察属性发生改变之前,willChangeValueForkey:一定会被调用,这就回记录旧的值。而当改变发生后,didChangeValueForKey:会被调用
  • 继而通过消息或者响应机制去调用observeValueForKey:ofObject:chaneg:context:
  • removeObserve:的时候 isa指针指回来