OC语言

一、分类
声明私有方法
分解体积庞大的类文件
把framework私有方法公开
特点
运行时决议
为系统类添加分类
实例方法
类方法
协议
属性(实际值生成了get和set方法)
分类添加的方法可以覆盖原类的方法,名字相同的分类会引起编译报错
多个分类方法时最后编译的最终生效,取决于编译顺序
能为分类添加成员变量,用关联对象的技术给分类添加实例变量
objc_getAssociatedObject
objc_setAssociateObject
objc_removeAssociatedObjects
objc_AssociationPolicy //关联策略
关联对象由AssociationsManager管理并在AssociationsHasMap存储
所有类的关联对象内容都在同一个全局容器中
如果关联对象的值为nil会擦除上次已经关联的内容
二、扩展
声明私有属性
声明私有方法
声明私有成员变量
分类和扩展的区别:编译时决议,只以声明的形式存在,多数情况下寄生于宿主类的m文件中,不能为系统类添加扩展
三、代理
代理是一种软件设计模式,iOS以@protocol形式实现
传递方法是一对一的,通知则是一对多
代理的的协议声明,协议定义委托方需要代理方实现的方法或者属性,require必须实现的,optional可实现的,规避循环引用。
四、通知
是使用观察者模式实现的,用于跨层传递消息的机制
传递方式一对多
五、KVO(key-value-observing)
kvo是观察者模式的又一种实现,使用isa混写isa-swizzling(isa回写技术)来实现kvo
比如A类系统会在运行时动态创建NSKVONotifying_A,将原来的类的isa指向新创建的类,重写起setter方法,NSKVONotifying_A实际上是A类的一个子类。通过重写setter方法负责通知所有观察者对象
重写setter方法中插入了willChangeValueForkey和didChangeValueForkey
通过kvc设置的value也能使kvo生效,应该会调用到对应的setter方法
通过成员直接赋值不能触发kvo,因为没有调用起setter犯法,可以调用willChangeValueForkey、didChangeValueForkey使其生效
六、KVC (key-value-coding)
valueForKey、setValueForKey
是会破坏面向对象的编程思想的
valueForKey的具体流程为:判断get方法存在,直接调用get方法,不存在则通过+(Bool)accessInstanceVariablesDirectly的返回值确定要不要获取对应的成员变量或相似的成员变量(getKey key isKey _key _getKey _isKey ),如果有则返回对应的值,如果没有回调用valueForUndefineKey抛出NSUndefinedKeyException异常
setValueForKey的具体流程:是否有对应的set方法,存在直接赋值,如果不存在通过+(Bool)accessInstanceVariablesDirectly的返回值确定要不要设置对应的成员变量或相似的成员变量(setKey key isKey _key _setKey _isKey ),如果有则返回对应的值,如果没有回调用setValueForUndefineKey抛出NSUndefinedKeyException异常
七、属性关键字
读写权限:
readonly readwrite(默认)
原子性:
atomic(默认)赋值和获取是相对线程安全的,对atomic的数组进行操作不能保证线程安全,
nonatomic
引用计数:
【OC语言】retain(mrc中使用)、strong(arc中使用)
assign:可以用用来修饰基本数据类型,修饰对象不改变其引用计数,会产生悬垂指针(指向曾经存在的对象,但该对象已经不再存在了,此类指针称为悬垂指针)
weak:修饰对象不改变其引用计数,所指向对象被释放会被只为nil,只能修饰对象
unsafe_unretained:(mrc,在arc中基本已经退出历史舞台了)
copy:浅拷贝会增加引用计数,只对内存地址进行复制,让对象指针和原对象指针指向同一片内存空间.深拷贝是内容拷贝,不会影响引用计数。可变对象不管是深拷贝开始浅拷贝都会进行深拷贝,copy之后返回的都是不可变对象。
@property(copy) NSMutableArray *array,如果赋值的是NSMutableArray copy后位NSArray 如果是NSArray copy后也是NSArray ,在调用array的添加方法时会报错。
八、面试题
1、MRC下给重写retain修饰属性的setter方法,
-(void)setObj:(id)obj{
if(_obj != obj){//不是为了判断重复对象多余开销,而是如果 _obj 为nil下面的release会报错
[_obj release];
_obj = [obj retain];
}
}

    推荐阅读