OC语言使用消息结构而非函数调用
OC由Smalltalk演化而来
在类的头文件尽量少引入其他头文件
多用字面量语法
多用类型常量,少用#define预处理指令
-
多用辅助的宏定义枚举类型:
typedef NS_ENUM(NSUInteger, State) { NormalState, HighlightState } typedef NS_OPTIONS(NSUInteger, Direction) { DirectionUp = 1<<0, DirectionDown = 1<<1 }
ABI(Application Binary Interface)应用程序二进制接口(可以在运行期间向类中新增实例变量,例如Category)
-
使用了@property,编译器会自动合成(autosynthesis),添加属性名前加下划线的实例变量名:
@synthesize name = _name
@dynamic 告诉编译器不要自动创建实现属性所用的实例变量,需要手动实现getter和setter方法,例如CoreData中NSManagedObject
属性特质:默认atomic,应尽量使用nonatomic属性,atomic属性会严重影响性能
直接访问实例变量速度快于属性访问,编译器所生成的代码会直接访问保存对象实例变量的那块内存
-
NSObject协议中两个用于判断等同性的关键方法:
- (BOOL)isEqual:(id)object; - (NSUInteger)hash;
如果isEqual判定两个对象相等,hash一定相等,反之则不然。重写isEqual方法一定也要重写hash,尽量利用hash来的到新的hash,保持高效:
- (NSUInteger)hash { NSUInteger firstNameHash = [_firstName hash]; NSUInteger lastNameHash = [_lastName hash]; NSUInteger ageHash = _age; return firstNameHash ^ lastNameHash ^ ageHash; }
NSArray的等同性判定深度:首先判断数组个数是否相同,同则在每个位置的对象调用其isEqual方法
collection会把各个对象按照其hash码分装到不同的箱子数组中,如果某对象在放入箱子后hash码变了,那么这个箱子对他来说就是错误的,因此要确保hash码不是根据对象的可变部分计算出来的
-
class cluster 类族(类族中的抽象基类):类方法创建实例,类似工厂方法:
+ (UIButton *)buttonWithType:(UIButtonType)type;
NSArray也是类族,由NSArray初始化方法返回的实例,其类型是隐藏在类族公共接口后面的某个内部类型,必须通过isKindOfClass来判断某个实例所属的类是否位于类族之中,而不能用isMemberOfClass或者==判断
开发这编写NSArray子类时,必须用一个实例变量来存放数组中的对象,NSArray并不会保存这些对象,因为NSArray本身只不过是包在其他隐藏对象外面的壳,仅仅定义了所有数组都需具备的一些接口,说白了就是一个抽象类而已。但对于这个自定义数组子类来说,可以用一个NSArray来保存其实例
关联对象(Associated Object)可以把两个对象连接起来,定义关联对象时可以指定内存管理语义,用以模仿定义属性时采用的拥有关系和非拥有关系
-
可以给关联对象指明存储策略,用一下方法管理关联对象:
void objc_setAssociatedObject(id object,void *key,id value,objc_AssociationPolicy policy) //设置 id objc_getAssociatedObject(id object,void *key) //获取 void objc_removeAssociatedObjects(id object) //移除指定对象的全部关联对象
-
存取关联对象相当于在对象上调用
[obj setObject:value forKey:key]
和[obj objectForKey:key]
方法,然而有个重要差别,设置关联对象用的键是个不透明指针,如果想让关联对象在两个键在调用isEqual时匹配到同一个值,就必须二者是完全相同的指针才行,因此在设置关联对象时通常使用静态全局变量做键:static void *Key = "key";