1、KVC的底层实现?
当一个对象调用setValue方法时,方法内部会做以下操作:
①检查是否存在相应key的set方法,如果存在,就调用set方法
②如果set方法不存在,就会查找与key相同名称并且带下划线的成员属性,如果有,则直接给成员属性赋值
③如果没有找到_key,就会查找相同名称的属性key,如果有就直接赋值
④如果还没找到,则调用valueForUndefinedKey:和setValue:forUndefinedKey:方法。
这些方法的默认实现都是抛出异常,我们可以根据需要重写它们。
2、__block和__weak修饰符的区别?
1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。
2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。
3.__block对象可以在block中被重新赋值,__weak不可以。
3、block和代理的区别,哪个更好?
代理回调更面向过程,block更面向结果。
如果需要在执行的不同步骤时被通知,你就要使用代理。
如果只需要请求的消息或者失败的详情,应该使用block。
block更适合与状态无关的操作,比如被告知某些结果,block之间是不会相互影响的。
但是代理更像一个生产流水线,每个回调方法是生产线上的一个处理步骤,一个回调的变动可能会引起另一个回调的变动。
要是一个对象有超过一个的不同事件,应该使用代理。
一个对象只有一个代理,要是某个对象是个单例对象,就不能使用代理。
要是一个对象调用方法需要返回一些额外的信息,就可能需要使用代理。
4、Object C中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码、方法又是什么?
线程创建有三种方法:使用NSThread创建、使用GCD的dispatch、使用子类化的NSOperation,然后将其加入NSOperationQueue;
NSThread创建线程的三种方法:
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"nil"];
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"我是分离出来的子线程"];
[self performSelectorInBackground:@selector(run:) withObject:@"我是后台线程"];
在主线程执行代码,就调用performSelectorOnMainThread方法。
如果想延时执行代码可以调用performSelector:onThread:withObject:waitUntilDone:方法;
GCD:
利用异步函数dispatch_async()创建子线程。
在主线程执行代码,dispatch_async(dispatch_get_main_queue(), ^{});
延迟执行代码(延迟·可以控制代码在哪个线程执行):
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{});
NSOperationQueue:
使用NSOperation的子类封装操作,再将操作添加到NSOperationQueue创建的队列中,实现多线程。
在主线程执行代码,只要将封装代码的NSOperation对象添加到主队列就可以了。
5、控制器view的生命周期?
控制器view是懒加载,用到的时候才加载。
生命周期方法调用顺序:
loadView-->viewDidLoad-->viewWillAppear
-->viewDidAppear-->viewWillDisappear-->viewDidDisappear
-->didReceiveMemoryWarning(收到内存警告)
-->viewWillUnload-->viewDidUnload
6、控制器View的加载过程?
当程序访问了控制器的View属性时会先判断控制器的View是否存在,如果存在就直接返回已经存在的View;
如果不存在,就会先调用loadView这个方法;如果控制器的loadView方法实现了,就会按照l