OC通过一套全新的语法,在C语言的基础上添加了面向对象的特性。
消息结果与函数调用区别在于:使用消息结构的语言,其运行时执行的代码由运行环境来决定;而使用函数调用的语言,则由编译器来决定。(函数调用的方式也提供了动态绑定,那就是多态)
编译期没有计算偏移量,运行时把每个类加载进内存,每个属性和方法都存在于映射表中。正是因为这个机制,所以分类和运行时编程才诞生。
UIAlertView增加参数可以通过,运行时关联属性来达到目的。(变量或者block)
但是这种不好,最好还是用继承的方式增加属性。
第四条:少用预处理指令
static const NSTimeInterval kAnimationDuration = 0.3;
类全局变量的static修饰符作用域是编译单元内;不加,编译器为他建一个外部符号,另一个编译单元同名会冲突。实际上static+const,编译器不会建符号,直接替换。
函数内的static作用域在函数内,但是存在于全局变量区会记录上次值。
类中的static函数只能本类调用,所以不会生成符号表,利于反编译。
作用域为整个工程的全局符号
// EOCAnimatedView.h
extern const NSTimeInterval EOCAnimatedViewAnimationDuration;
// EOCAnimatedView.m
const NSTimeInterval EOCAnimatedViewAnimationDuration = 0.3;
第五条:枚举的善用
NS_ENUM 全部情况
NS_OPTIONS 各种选项,可以自由组合
枚举用switch进行分之判断的时候,别用default分之。这样的话,增加一个状态,编译器会报警告。
第十二条:消息转发机制
方法列表找不到
+ (BOOL)resolveInstanceMethod:(SEL)selector
+ (BOOL)resolveClassMethod:(SEL)selector
选择其他接受者
- (id)forwardingTargetForSelector:(SEL)selector
转发其他接受者
- (void)forwardInvocation:(NSInvocation*)invocation
第二十七条:匿名类隐藏实现细节
头文件中引入了C++文件,会造成这个类被编译成C++文件。如果别人再引入这个文件,影响的范围会很大。
所以引入C++文件的时候,把他放在.m文件中,这样编译的时候就只会影响自身。
头文件的属性只读,匿名类可以修改成可写。
对象关联
把对象本身当做字典,把关联到对象的属性理解为key。但是这个key是不透明的指针,后面如果需要取出这个key的值,我们需要用到这个key,所以把key定义为静态全局变量。
- (void)setCyj:(NSString *)cyj
{
objc_setAssociatedObject(self,@selector(cyj),cyj,OBJC_ASSOCIATION_COPY_NONATOMIC);
//关联的key是getter方法的消息,所以getter方式的key可以直接是cmd
}
- (NSString *)cyj
{
return objc_getAssociatedObject(self, _cmd);
}
GCD
1、可以用串行队列代替互斥锁
_syncQueue = dispatch_queue_create("com.effectiveobjectivec.syncQueue", NULL);
- (NSString*)someString {
__block NSString *localSomeString;
dispatch_sync(_syncQueue, ^{
localSomeString = _someString;
});
return localSomeString;
}
- (void)setSomeString:(NSString*)someString {
dispatch_sync(_syncQueue, ^{
_someString = someString;
});
}
写操作的可以用同步或者异步,但是异步会是copy一份block内容,所以在copy的消耗和执行时间的消耗之间选择。
2、并行队列
_syncQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
如果需要队列元素单独执行,可以使用栅栏
void dispatch_barrier_async(dispatch_queue_t queue,dispatch_block_t block);
void dispatch_barrier_sync(dispatch_queue_t queue,dispatch_block_t block);
3、GCD 比 performSelector 好,因为performSelector 传递的参数很局限,而且ARC内存释放也做不到。
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC));
dispatch_after(time, dispatch_get_main_queue(), ^(void){
[self doSomething];
});
4、GCD 和 操作队列
GCD是纯C的API,操作队列是在GCD上封装的OC。
操作队列好处:1.可以取消某个操作。2.指定元素之间的依赖关系。3.KVO监测NSOperation的属性。4.指定优先级。