第一章:对象、消息、运行时
1. 了解oc
- 源自smalltalk ,和其他面向对象语言的区别是前者是基于消息传递的,后者是基于函数调用的
- oc 是c的超集,使用动态绑定的消息结构,在运行时才会检查对象类型,应该执行何种代码,由运行期环境决定而非编译器决定,而其他语言不同的点在于运行的代码由编译器决定。
- 采用 “引用计数”管理对象内存, 指针的是存放在栈上面的,栈帧弹出时自动清理,而指针指向的对象是分配在堆上面的,需要手动管理。非指针变量可能采用栈空间,例如CGRect 等,这厮一种结构性对象,内部保存基本的int ,float 等基本类型,与创建oc 对象相比,创建对象还需要额外的开销,性能会受影响,所以这种数据采用非oc 对象就可以了。
2. 在类的头文件中尽量少引入其他头文件
- 目的为了减少编译时间,另外也为了减少类之间的耦合性
- 如果采用 “向前声明” @class 关键字解决.h 文件里面引入其他类的问题,同事记得在.m 文件中引入相应的类头文件,可以解决循环引用的问题。
- 无法使用前向声明的时候,可以考虑将类的协议声明放入分类里面
- 可以考虑将协议统一放入一个单独的头文件中,然后将其引入
待完善。。。。。
3. 多用字面常量,少用与之对应的语法,是一种 #语法糖#
基本类型:NSNumber * test1 = @1 或者 NSNumber * test1 = @(1)
等价于 NSNumber * test1 = [NSNumber numberWithInt:1]
定义数组:
NSArray * array = @[];
NSMutableArray * arrayM = @[].mutableCopy;
定义字典:
NSDictionary * dic = @{};
NSMutableArray *dicM = @{}.mutableCopy
*****注意定义集合对象是保证元素不能为nil ,否则就会崩溃****
4. 多用类型常量,少用#define 预编译指令
#define AnimationDuration 1.0
//建议采用如下的方式
static const NSTimeInterval kAnimationDuration = 1.0;
分析:
-
预编译指令没有类型信息,便以前不会类型检查,只会进行查找和替换操作,另外多出重复定义也不会检查出来,值被无意修改也不会报错
-
关于常量命名,如果只是在该文件内部使用那么前面通常加k 前缀,static 能够是作用域限于文件内部
static const NSTimeInterval kAnimationDuration = 1.0;
- 如果只是在其他文件也要使用,通常用类名作为前缀,防止重名,并且采用extern 关键字声明全局常量
头文件:
extern const NSTimeInterval ClassNameAnimationDuration;
实现文件:
const NSTimeInterval ClassNameAnimationDuration = 1.0;
指针类型>
头文件:
extern NSString * const ClassNameAnimationDuration;
实现文件:
NSString * const ClassNameAnimationDuration = 1.0;
- 尽量不要在头文件中定义常量,而应该在实现文件中
由于采用static const 声明的静态局部常量不在全局符号表中出现,但是用extern 修饰的全局常量会再全局符号表中出现,所以为了防止重名,应该采用类名作为前缀
5. 用枚举表示状态,选项,状态码
a. 枚举的定义使用
enum DownLoadStatus{
DownLoadStatusFinished,
DownLoadStatusError
};
enum DownLoadStatus type = DownLoadStatusFinished;
为了省去enum定义关键字,在上者的基础上重新命名:
typedef enum DownLoadStatus DownLoadStatus;
DownLoadStatus type = DownLoadStatusFinished;
-------枚举后来的新增特性,可以指明底层所用的数据类型
语法格式:enum DownLoadStatus :NSInteger {/*...*/};
b. 位移枚举
- 选项之间可以通过 “按位或” 彼此组合出新的类型
- 可以通过 “按位与” 判断当前值,是否启动了某个选项
1.
enum UIViewAutoresizing{
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
特点:每个值的二进制表示中,只有一位表示1,那么按位或可以组合出新的选项:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight 表示高和宽
2.
enum UIViewAutoresizing resziging = UIViewAutoresizingFlexibleLeftMargin;
if (resziging & UIViewAutoresizingFlexibleLeftMargin){
// 值是UIViewAutoresizingFlexibleLeftMargin
}
c. 系统的Foundation框架提供了两个新的宏用来定义枚举,可以在定义的时候指定用于保存枚举值的底层数据类型。
一个是普通的NS_ENUM 另外一个是可选枚举NS_OpOTIONS
typedef NS_ENUM (NSInterger, NetWorkConnectionStatus){
NetWorkConnectionStatusDisConnected,
NetWorkConnectionStatusConnecting,
NetWorkConnectionStatusConnected
};
typedef NS_OPTIONS (NSInterger, DeviceDirection){
DeviceDirectionUp = 1 << 0,
DeviceDirectionDown = 1 << 1,
DeviceDirectionLeft = 1 << 2,
DeviceDirectionRight = 1 << 3
};
NS_ENUM 宏展开后:
typedef enum NetWorkConnectionStatus :NSInterger NetWorkConnectionStatus;
enum NetWorkConnectionStatus: NSInterger {
NetWorkConnectionStatusDisConnected,
NetWorkConnectionStatusConnecting,
NetWorkConnectionStatusConnected
}
枚举宏的作用在于是对不同编译器特性的一种组合, 不需要手动去判断是否可以采用新的一些特性,若需要枚举值进行组合那么应采用option枚举宏,否则采用普通的NS_ENUM。
d. 采用枚举的做switch分支语句的时候,不要加上default 分支,这样的话,可以利用编译器的特性,当新加入一种类型的时候,如果分支没有实现,那么编译器就会报警提示缺少新加入的枚举类型
网友评论