ios面试题(整理)
- ios常用的设计模式有哪些?
MVC模式、委托模式、观察者模式(kvo、kvc、通知机制)、单例模式.
我对观察者的理解:就好像一个人在炒股,一夜暴富,他的状态从贫穷变为富有.他通知他的亲朋好友,然后他的亲朋好友根据自身要求改变.
一个对象在自身状态发生改变后,通知监视他的对象,监视他的对象根据自身条件发生改变.
对通知机制的理解:就相当于我们平时发说说,将我们当前的状态发布在QQ空间,对你感兴趣的人,会将你设为特别关注,只要你发动态,那个人就会收到通知.
一个对象将他的状态发布在通知里面,对他感兴趣的对象,可以申请在特定通知发布时接受这个通知.
- kvc的底层实现原理是什么?
Kvc在单类情况下,用setValue:forkey(相当于set) 和valueForKey(get)访问属性.在类嵌套下,用setValue: forKeyPath(set)和valueForKeyPath(get)访问.如果访问不到,就会报出setValue:forUndleKey这个错误.
在ios开发中,我们可以通过set和get方法来访问对象的属性,若一个对象的属性没有提供get和set方法,外界就失去了访问这个属性的访问渠道,针对这种情况,ios提供了kvc机制,可以间接访问对象的属性.操作属性,获取key路径,处理不存在的key.
Kvc是一种通过对象的属性名称,将其作为key,简接的访问该属性的机制.假设有一个Person类,该类有一个name属性,对于setValue:属性值 forKey:@”name”这句代码,底层的执行机制如下:
(1) 程序会优先考虑setName方法,代码会通过setter方法完成设置.
(2) 若Person类没有name属性的setter方法,kvc机制会搜索该类中名称为_name的成员变量,无论成员变量在类的接口部分定义,还是在类的实现部分定义,甚至用任意的访问修饰符,底层实际上就是对名称为_name的成员变量赋值.
(3) 若Person类中既没有setName方法,也没有定义名称为_name的成员变量,那么,kvc机制就会搜索该类名字为name的成员变量,无论该成员变量是在类的接口部分定义,还是在类的实现部分定义,甚至是用任意的访问修饰符修饰,这条kvc代码底层就是对name成员变量赋值.
(4) 如果以上3条没有找到,系统会执行该对象的setValue:forUndefinedKey方法.同理,valueForKey:@”name”这句代码也会遵循相同的方式,一步一步搜素.
- Kvo底层实现原理
Kvo机制是由oc强大的runtime所支持的,程序在运行的过程中,系统会自动地通过runtime给被监听的对象创建一个子类,其名称为”NSKVONotifying_类名称”,并重写该子类的set方法,在set方法调用监听者的observeValueForKeyPath:ofObject:change:context:方法.
单例模式:如果全局都用到了.在内存中可以只创建一份,节省内存.
类工厂方法的实现
(void)sharedSingleton{
Static Dispatch_once_t onceToken;
Dispatch_once (&onceToken,^{
_ShareInstance = [super allocwithZone:zone];
});
return _shareInstance;
}
//用copywithzone重写
(void)copyWithZone:(struct_NSZone *)zone{
return_shareInstance;
}
我们为什么用GCD的dispatch_once实现单例呢,因为Dispatch_once有两个参数,dispatch_once_t,可以判断线程是否被调度,保证线程安全.dispathc_block_t,保证代码块只被调用一次.优点:线程安全,很好的满足了静态分析器的要求,能够自动应用计数兼容,仅仅只需要少量的代码.
缺点:仍然可以运行创建一个非共享的实例,可以使用alloc实例化一个对象.
Delegate传值
两个控制器,第一个控制器要向第二个控制器传值,第一个控制器就需要声明一个代理协议,把要传递的参数写在协议的声明方法里.在第一个控制器声明里,引入@property(nonatomic,weak)id< ----delegate>delegate属性.在实现文件里,需要判断一下协议是否响应了协议方法.
If ([_delegate isResponseSelector:@selector(_____delegate声明的方法) ]{
};
在第二个控制器里面,实现声明的代理方法.这样就完成了传值.