1、了解Objective-C语言的起源
- OC语言使用“消息结构” 而非“函数调用”
消息结构:
Object *obj = [Object new];
[obj performWith:parameter1 and:parameter2];
特点:运行时的代码由运行环境来决定。
函数结构:
Object *obj = new Object;
obj->perform(parameter1,parameter2);
特点:运行时的代码由编译器来决定。
- OC是C的“超集”,所以C语言的所有功能在编写OC代码时依然适用!
OC中的内存模型:
NSString *nameString = @“小伙子”;
上面就是说:声明了一个名为 nameString 的变量 ,其类型为NSString *
也就是说,此变量为指向NSString 的指针。当然了不止NSString这样声明,所有Objective-C的对象都必须这样声明。原因:对象所占内存总是分配在“堆空间”中,而不会分配到“栈”上。 - 在OC中,你还会碰到一些不需要 *的变量。他们可能会使用“栈空间” 这些变量保存的不是Objective-C对象。举个例子
struct CGRect {
CGPoint origin;
CGSize size;
};
typedef struct CGRect CGRect;
系统框架都在使用结构体。因为使用Objective-C来做的话会影响性能(创建对象、分配内存、释放内存)。如果只是保存int、float、double、char这些“非对象类型” 通常使用CGRect结构体就可以了。
2、在类的头文件中尽量少引入其他头文件
- 现象:
Objective-C创建文件分为.h(头文件)和.m(实现文件)
假如在某个头文件中引入一些根本用不到的头文件。那么程序也会引入头文件的内容。这样会增加编译时间。 - 建议:
除非确实有必要,否则不要引入头文件。
应该在实现文件中引入要使用的头文件,降低类之间的耦合。
3、多用字面量语法,少用与之等价的方法
- 实现
语法创建:
//多种类型的数值
NSNumber *number = [NSNumber numberWithInt:1];
//数组创建
NSArray *array = [NSArray arrayWithObjects:@"1",@"2",@"3", nil];
//字典的创建
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"Mary",@"name",@"Secr",@"name1" ,nil];
字面量创建
//数值创建
NSNumber *number = @1;
int a = 1;
float b = 4.23f;
//数组创建
NSArray *array = @[@"1",@"2",@"3"];
//字典的创建
NSDictionary *dictionary = @{@"Mary":@"name",@"Secr":@"name1"};
- 结论
- 使用字面量语法创建字符串、数值、数组、字典。与创建此类对象的常规方法相比,这么做更加简明扼要。
- 用字面量创建数组或者字典时,若值中有nil,则会抛出异常。因此,务必确保值里不含nil。
4、多用类型常量,少用#define预处理指令
- 编写代码时候经常要定义常量。
例如一个动画的播放时间
#define ANIMATION_DURATION 0.3
预处理指令会把源代码中的ANIMATION_DURATION字符串替换为0.3。
but、这样定义出来的常量没有类型信息。- 名字(duration)这个词看上去与时间有关,但是代码中并没有标出。
- 假如其他文件中有ANIMATION_DURATION ,也会一律替换成0.3
- 可以这样解决:
static const NSTimeInterval kAnimationDuration = 0.3;- 包括了类型信息、有助于编写开发文档、让接手代码的人更易读。
- 试图修改const修改的变量,那么编译器会报错。
- 注意:
- 常量的命名规则:
常量局限于实现文件之内,在前面加字母k。
若是常量在类之外可见,那么要以类名为前缀。比如SCViewClassAnimationDuration。
- 常量的命名规则:
- 外界可见的常值变量:
- 这种常量放在“全局符号表”中,以便可以在定义该常量的编译单元之外使用!
.h中
- 这种常量放在“全局符号表”中,以便可以在定义该常量的编译单元之外使用!
extern NSString *const SCNameStringConstant;
.m中
NSString *const SCNameStringConstant = @"Peter";
- 原理:
编译器看到头文件中的extern关键字后,就知道在全局符号表中有一个名叫 SCNameStringConstant 的符号。
编译器无需查看其定义,允许代码使用此常量。因为它知道肯定能找到这个常量。 - 注意:
此常量必须要定义且只能定义一次。通常是定义在与声明常量的头文件相关的实现文件里。链接器会把此目标文件和其他目标文件相链接,形成二进制文件,凡是用到SCNameStringConstant的地方都能解析。
因为符号要放在全局符号表里,所以命名的时候一定要注意。最好是用与之相关的类名做前缀!
5、用枚举表示状态、选项、状态码
- 枚举:enum
系统框架中频繁用到此类型:
比如创建UIButton时候
typedef NS_ENUM(NSInteger, UIButtonType) {
UIButtonTypeCustom = 0, // no button type
UIButtonTypeSystem NS_ENUM_AVAILABLE_IOS(7_0), // standard system button
UIButtonTypeDetailDisclosure,
UIButtonTypeInfoLight,
UIButtonTypeInfoDark,
UIButtonTypeContactAdd,
UIButtonTypeRoundedRect = UIButtonTypeSystem, // Deprecated, use UIButtonTypeSystem instead
};
枚举只是一种常量命名方式。每种状态用一个易读的值来表示,这样更方便理解。编译器会为枚举分配一个独有的编号,从0开始,每个枚举递增1。
- 比如状态一般分为“OK”和“Error”。只能选择其中一种,不可能出现2种。
我们可能通过枚举这样做
typedef enum _TTGState {
TTGStateOK = 0,
TTGStateError,
TTGStateUnknow
} TTGState;
//指明枚举类型
TTGState state = TTGStateOK;
用的时候就这样:
- (void)dealWithState:(TTGState)state {
switch (state) {
case TTGStateOK:
//...
break;
case TTGStateError:
//...
break;
case TTGStateUnknow:
//...
break;
}
}
```
- 选项:就是说一个“选项变量”的类型要能够同时表示一个或多个组合的选择。
比如说iPhone 可以支持多个方向。
//方向,可同时支持一个或多个方向
typedef enum _TTGDirection {
TTGDirectionNone = 0,
TTGDirectionTop = 1 << 0,
TTGDirectionLeft = 1 << 1,
TTGDirectionRight = 1 << 2,
TTGDirectionBottom = 1 << 3
} TTGDirection;
好处就是我们选项变量可以如下表示:
//用“或”运算同时赋值多个选项
TTGDirection direction = TTGDirectionTop | TTGDirectionLeft | TTGDirectionBottom;
//用“与”运算取出对应位
if (direction & TTGDirectionTop) {
NSLog(@"top");
}
if (direction & TTGDirectionLeft) {
NSLog(@"left");
}
if (direction & TTGDirectionRight) {
NSLog(@"right");
}
if (direction & TTGDirectionBottom) {
NSLog(@"bottom");
}
一般来说,我们不能指定枚举变量的实际类型是什么,就是说,我们不知道枚举最后是int型,还是其他的什么类型。但是从C++ 11开始,我们可以为枚举指定其实际的存储类型。
enum TTGState : NSInteger {/*...*/};
Foundation框架中定义了一些辅助的宏,这些宏具备了向后兼容的能力(判断编译器是否支持新的枚举特性,不支持就用老的语法来定义枚举)。
- 在iOS程序中,最好所有的枚举都用“NS_ENUM”和“NS_OPTIONS”定义,保证统一。
### 接下来也将会继续整理。如果觉得有用请点个喜欢!
### 您的支持将是我继续写作的动力!谢谢。
[观“编写高质量iOS与OC X代码的52个有效方法”有感(一)· 熟悉Objective-C](http://www.jianshu.com/p/0876e60d3160)
[观“编写高质量iOS与OC X代码的52个有效方法”有感(二)· 对象、消息、运行时](http://www.jianshu.com/p/1aac4fb98888)
[观“编写高质量iOS与OC X代码的52个有效方法”有感(三)· 接口与API设计](http://www.jianshu.com/p/5d9e61db2a01)
[观“编写高质量iOS与OC X代码的52个有效方法”有感(四)· 协议与分类](http://www.jianshu.com/p/0944e1e276ff)