1、对象内部尽量直接访问实例变量
- 直接访问实例变量不会进行方法派发,直接访问对应内存(读直接用实例变量,写为了调试可以使用属性)
- 直接访问实例变量不会触发KVO
2、判断两个对象,或者两个值是否相等
1、== 能判断不管对象还是基础类型是否相等。基础类型比较的是值内容,对象比较的是指针是否相同(NSString 比较独特,因为字符串驻留的优化技术,所有的字符串都是在一个共享字符串池中的,将不可变字符串的值赋值给了不同的指针.)
2、等同性判断:-isEqual方法和-hash方法
3、通过增加唯一标识符来减少执行深度
4、容器中的可变类等同性不可控
3、关联(一般用于类扩展中增加属性)
4、运行时
==运行时有一些机制,其中最主要的是消息机制。消息机制就是在运行时才能确定调用的是哪个函数==
- 交换方法(可以用于调试日志打印)
- 动态添加方法performSelector
- 给分类添加属性
- 字典转模型,模型转字典
5、消息转发机制
两个阶段:1.动态方法解析;2、完整的消息转发机制
graph LR
+resolveInstanceMethod-->class_addMethod
class_addMethod-->forwardingTargetForSelector
forwardingTargetForSelector-->forwardInvocation
6、调试方法“黑盒方法”
graph LR
class_getInstanceMethod-->method_exchangeImplementetions
7、全能初始化方法
- 如果子类的全能初始化方法与超类方法的名称不同,需要覆写超类的全能初始化方法
- 提供一个全能初始化方法,其他初始化方法调用他
- 子类不适用超类初始化方法则覆写抛出异常
8、尽可能使用不可变对象
- 尽可能创建不可变的对象
- 若某属性仅可对于对象内部修改,则在分类中将其readonly改为readwrite
- 不要把可变的collection作为公开属性
9、oc错误模型
- NSError返回有两种方式
- 通过代理用NSError *error参数返回(代理传值)
- 由输出参数返回给调用者NSError **error
int a 做参 a值不会变
int *a 做参 *a值不会变,a会变
int **a 做参 **a值不会变,*a会变,a会变
10、深浅拷贝
- copy出来的字符串一定是不可变字符串,如果传入的是可变字符串,会发生深拷贝为不可变字符串,否则为浅拷贝
- mutablecopy,一定是深拷贝,拷贝出来的一定是可变字符串或者数组,即使传入的是不可变字符串或者数组
- 对于集合类的可变对象来说,深拷贝并非严格意义上的深复制,只能算是单层深复制,即虽然新开辟了内存地址,但是存放在内存上的值(也就是数组里的元素仍然之乡员数组元素值,并没有另外复制一份),这就叫做单层深复制
- 集合对象的完全深拷贝
//归解档
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:marry1];
NSArray *marray2 = [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:data error:nil];
//深拷贝函数
- (instancetype)initWithArray:(NSArray<ObjectType> *)array copyItems:(BOOL)flag;
11、通过委托与数据源进行对象间的通信
- 委托用于本体与雇主进行通信,让雇主完成本体无法完成的动作
- 数据源用于本体从雇主那边获取最新的数据
- 可以使用位段的结构体,将委托对象是否响应相关协议方法进行缓存,不用每次都执行判断函数
12、分类
- 分类必须引入头文件
- 最好不要在分类中声明属性
- 使用class-continuation分类隐藏实现细节(可以将readonly属性修改为readwrite)
13、通过协议提供匿名对象
id<protocol> obj
网友评论