标签:属性 not sig cat assign 理解 映射 讲解 []
Tips 1 Objective-C 的起源
Tips 2 头文件中减少引用
@class ClassName;
来进行Forward DeclaringUITableView
和 UITableViewDelegate
)因为只有与委托类放在一起才有意义,所以就不用单独分离头文件,应该放到定义 UITableView
的头文件中Tips 3 使用字面量
NSString
,NSNumber
,NSDictionary
和 NSArray
使用类似 @"String"
,@1
,@[]
和 @{}
不要使用等价方法Tips 4 使用类型常量
定义常量时,使用类型常量不要使用 #define
,比如:
// 使用如下的方式定义 static const NSInteger kInteger = 1; // 而不是 #define SOME_INTEGER 1
这样可以给编译器类型信息,在编译时和开发时能够进行类型检查
每一个 m 文件都是一个编译单元
使用static
声明表示在本编译单元有效,若需要将变量放到全局有效,那么需要使用 extern
使用 const
表示常量不会被修改
Tips 5 使用枚举表示状态,选项,状态码
NS\_ENUM
宏定义枚举,因为枚举是按顺序的,也就是枚举值是1,2,3…… 这样的NS\_OPTION
定义选项,因为选项是按位的,也就是选项是通过 1 << 0
,1 << 1
这样来定义的,表示1右移Tips 6 理解属性
使用属性,而不是实例变量,在代码中使用点(.
)操作符访问属性
属性会生成对应的实例变量,一般是属性名前加下划线,也可以在类的实现代码中通过 @synthesize
来指定,例如:@synthesize firstName = _firstName
使用 @dynamic
告诉编译器不需要生成对应的getter 和 setter
属性的 attribute 会影响编译器生成的代码
atomic / nonatomic,原子性,一般我们都使用 nonatomic
因为 iOS 的属性锁开销很大,另外 atomic
并不能保证线程安全
readwrite / readonly,读写或是只读
内存管理要注意的
nil
nil
-copy
方法获得新的对象,建议所有不可变的 NSString
,NSArray
,NSDictionary
都使用这个方法,可变的类型不可以使用这个方法Tips 7 对象内部直接访问实例变量,设置时通过属性方法
Tips 8 对象相等
==
只是比较对象指针是否相等,深层的比较需要使用 -isEqual:
方法-isEqual:
返回返回真,那他们的 -hash
方法要返回同一个值,但是 -hash
方法返回同一个值的两个对象 -isEqual:
不一定为真-hash
方法用作在集合类型中计算索引,如果所有对象的这个方法都返回同一个值,那么在集合中检索对象性能会很差,这个方法应该使用计算速度快,并且不容易碰撞的方法实现NSString
的 -isEqualToString:
方法)-hash
方法得到的值不会变,如果放入集合后,修改集合内对象导致 -hash
的值发生变化,那么集合对象是不会知道 -hash
值有变化,并且将来会出现奇怪的错误Tips 9 类簇
-isKindOfClass:
来判断,不可使用 [object class] == [Class class]
或者 -isMemberOfClass:
来判断Tips 10 Associated Object
可以为已有的对象创建新的属性
设置方法
void objc\_setAssociatedObject(id object, void *key, id value, objc\_AssociationPolicy policy)
id objc\_getAssociatedObject(id object, void *key)
id objc\_removeAssociatedObject(id object)
关联类型和属性的对应(上面 policy 的值)
key 的值,使用一个 opaque pointer,一般来说使用静态全局变量
Tips 11 理解 objc\_msgSend
的作用
Objective-C 中所有的方法,都是 C 函数
给某个对象的消息全部都是动态发送的,如下
id returnValue = [someObject messageName:parameter]
objc\_msgSend
函数处理消息发送,得到 id returnValue = objc_msgSend(someObject, @selector(messageName:), parameter)
objc\_msgSend
会去 someObject
的方法列表中对应的函数,如果找不到,那么沿着继承体系继续找,还是找不到,那么会进行消息转发操作(在 Tips 12 讲解)Objective-C 的运行时已经做了很多保证让这套机制性能很好
objc\_msgSend
一样的原型,这样在 objc\_msgSend
从对象的方法列表中找到对应函数时,可以直接跳转过去,不需要重新在调用堆栈中插入新的栈帧Tips 12 理解消息转发
因为 Objective-C 使用运行时来决定具体调用的方法,所以在运行之前是不知道一个对象是否能响应特点方法的
消息转发是在一个对象收到无法解读的消息时触发的机制
消息转发的过程
NSInvocation
对象里面,最后再给接收者一次处理的机会动态方法解析
过程,下面两个过程是渐进的,第一个失败了,那么执行第二个
+ (BOOL)resolveInstanceMethod:(SEL)selector
询问类是否能新增一个实例方法处理这个消息+ (BOOL)resolveClassMethod:(SEL)selector
询问类是否能增加一个类方法来处理这个消息用法,相关方法实现已经写好,只等着运行时去动态插入到类里面就行了
@dynamic
属性消息转发
备选的消息接收者
- (id)forwardingTargetForSelector:(SEL)selector
询问接收者是否有另一个对象来处理这个消息完整的消息转发
NSInvocation
对象,把 selector,target 和参数都放进去- (void)forwardInvocation:(NSInvocation *)invocation
方法吧消息指派给目标对象NSObject
NSObject
的 - (void)forwardInvocation:(NSInvocation *)invocation
只是简单的调用 - (void)doesNotRecognizeSelector:
方法抛出异常,所以一般向对象发送他没有实现的方法都会通过这个方法抛出异常Tips 13 Method Swizzling(原书叫方法调配技术,看到这个名词,第一句话是什么鬼)
很多时候,这个技术被大家称为黑魔法,但是其实他做的只是在运行时交换方法的实现而已
所有的方法都是在对象中是一个 IMP
指针,指针原型 id (*IMP)(id, SEL, ...)
每个类通过一张映射表来映射可相应的 selector 和对应 IMP
指针的关系
可以做 AOP
对方法的操作
使用 void method_exchangeImplementations(Method m1, Method m2)
来交换两个方法
使用 Method class_getInstanceMethod(Class aClass, SEL aSelector)
来获取类的实例方法
常规的 Method Swizzling 做法
1 // 在 Category 的定义文件中增加我们将要用来替换的方法 2 @interface NSString (MethodSwizzling) 3 - (NSString *)ms_myLowercaseString; 4 @end 5 6 // 在 Category 的实现文件中,进行交换 7 @implementation NSString (MethodSwizzling) 8 - (NSString *)ms_myLowercaseString { 9 // 在调用原方法前做点其他的事情 10 // 注意这里并不是递归调用,而是因为我们交换了 lowercaseString 和 ms_myLowercaseString 的实现,所以这里调用 ms_myLowercaseString 实际上是在调用 lowercaseString 方法 11 NSString *s = [self ms_myLowercaseString]; 12 13 // 在调用完原方法后做点其他的事情 14 return s; 15 } 16 17 + (void)load { 18 Method m1 = class_getInstanceMethod([NSString class], @selector(lowercaseString)); 19 Method m2 = class_getInstanceMethod([NSString class], @selector(ms_myLowercaseString)); 20 method_exchangeImplementations(m1, m2); 21 } 22 @end
Tips 14 理解类对象
Class
类的变量Class
对象是一个 objc_class
的结构体,里面保存了类的元数据Class
类同样有元类(metaclass)Class
对象的元类,也继承于该类超类的元类-isMemberOfClass:
可以判断某个对象是否是某个类的实例-isKindOfClass:
可以判断某个对象是否是某个类或其子类的实例EFFECTIVE OBJECTIVE-C 2.0 TIPS 总结 CHAPTER 1 & CHAPTER 2
标签:属性 not sig cat assign 理解 映射 讲解 []
原文地址:http://www.cnblogs.com/noark9/p/6110646.html