前言
没事要多读书,读好书。
笔记
类的头文件中尽量少引入其他头文件
- 使用向前声明(forward declaring)
@class
减少编译时间,避免相互引用 - 非委托协议的协议,单独写一个头文件
- 使用向前声明(forward declaring)
多用类型常量,少用
#define
预处理指令#define
只是简单的替换,不包含类型信息,重新定义时编译器也不会产生警告。.m 中如定义个时间常量,比起
#define ANIMATION_DURATION 0.3
可以使用static const NSTimeInterval kAnimationDuration = 0.3
如果需要对外公开常量
.h 中
extern NSString * const ConstantString
,.m 中NSString * const ConstantString = @"ConstantString";
理解“块”
全局块、栈块及堆块
1
2
3
4
5
6
7
8
9
10
11
12
13void (^block)();
if (condition) {
block = ^{
NSLog(@"Block A");
};
} else {
block = ^{
NSLog(@"Block B");
};
}
block();定义在 if 及 else 中的两个块都分配在栈内存中,编译器会给每个块分配好栈内存,然而离开相应范围之后,编译器有可能把分配给块的内存覆写掉。这段代码可以编译但运行时时而正确时而错误。若编译器未覆写待执行的块,则程序照常运行,若覆写,则程序崩溃。
为解决此问题,可给块对象发送 copy 拷贝,就可以把块从栈复制到堆上。块复制到堆上后就变成带引用计数的对象了。
1
2
3
4
5
6
7
8
9
10
11void (^block)();
if (condition) {
block = [^{
NSLog(@"Block A");
} copy];
} else {
block = [^{
NSLog(@"Block B");
} copy];
}
block();全局块不会捕捉任何状态,所在全局内存区,在编译期已经完全确定。全局块的拷贝操作是个空操作,因为全局块不可能为系统回收,相当于单例。
1
2
3void (^block)() = ^{
NSLog(@"Block A");
}