Effective Object C 2.0——熟悉Object-C
来源:互联网 发布:herry it 编辑:程序博客网 时间:2024/06/05 04:37
Object-C的起源和特性
- 消息结构语言,所执行代码由运行环境来决定而不是编译器
- 由运行期组件(Runtime Component)而非编译器来完成。
- C的超集,所有的Object-C的对象必须分配在堆上。
在类的头文件中尽量少引入其他头文件
- 向前声明,参考C++的向前声明, 在头文件中@class ClassName.但在实现类中需要#import “class.h”,因为实现类中要使用这个类,必须知道其所有接口细节。
- 向前声明解决了相互引用问题。也要注意的是,使用#import而非#include不会导致死循环编译,但是类中有一个类会无法被正确编译。
总结:
1. 除非有必要,否则不要引入头文件,一般来说,在某个类的头文件中使用向前声明来提及别的类,在实现文件中引入那些类的头文件,这样可以降低类之间的耦合。
2. 当要声明一个类遵循一项协议时,尽量把该类遵循某协议(SubClass: SuperClass)这条声明移到class-continuation分类,在实现文件里写。如果不行就把协议单独放到一个头文件里,然后将其引入。
多用字面量语法,少用与之等价的方法
NString的两种初始化方式
1. NSString *test = @”test”;
2. NSString *test = [[NSString alloc] init];
尽量使用第一种,第一种叫做字符串字面量,代码短而且易读
同理,对于NSNumber两种初始化方式
- NSNumber *someNumber = @1; NSNumber *floatNumber = @1.5f;
- NSNumber *someNumber = [NSNumber numberWithInit:1];
也是推荐第一种
NSNumber *boolNumber = @YES;
NSNumber *charNumber = @’a’;
字面量语法也适合表达式 NSNumber express = @(x y);
对于NSArray,也有两种创建方式
- NSArray *animals = [NSArray arrayWithObjects:@”cat”, @”dog”, nil];
- NSArray *animals = @[@”cat”, @”dog”];
第二种更利于数组操作,比如取数据时
第一种 NSString *dog = [animals objectAtIndex:1];
而第二种是 NSString *dog = animals[1];
注意 字面量语法实际上是一种语法糖,NSArray操作等效于先创建一个数组,然后把方括号所有对象加入数组,所以当数组元素有nil时会抛出异常。arrayWithObjects会依次处理各个参数,直到遇到nil,所以nil后面的会无法加入,所以相对于抛异常,更不安全。
字面量字典,NSDictionary
- NSDictionary *person = [NSDictionary dictionaryWithObjectsAndKeys:@”Matt”, @”firstName”, @”Green”, @”lastname”, [NSNumber numberWithInit: 28], @”age”, nil];
- NSDictionary *person = @{@”firstname”: @”Matt”, …};
同样的问题,值不能有nil;
访问的时候,第一种NSString *lastName = [person objectForKey:@”lastname”];
第二种 NSString *lastname = person[@”lastname”];
可变数组与字典
传统的修改方式如下
[array replaceObjectAtIndex:1 withObject: @"dog"];[dict setObject:@"Green" forKey:@"lastname"];
字面量修改方式
array[1] = @"dog";dict[@"lastname"] = @"Green";
局限性,必须使用Foundation框架内的类,比如以上几种类,其他类或者它们的子类都不行。
多用类型常量,少用#define预处理指令
以前C或者Object-C定义常量如下
#define ANIMATION_DURATION 0.4
问题是编译器会把所有的遇到的ANIMATION_DURATION替换为0.3
所以定义时间间隔如下:
static const NSTimeInterval kAnimationDuration = 0.3;
方便阅读,方便理解含义。另外如果常量局限于某个编译单元(也就是某个实现文件内),则前面加k,若常量在类之外可见,则通常以类名为前缀。
定义常量的位置,不应该像预处理文件一样放到头文件,这样引入头文件的都会出现这个define,static const的常量也不应该出现在头文件,因为OC没有名称空间??概念,这就等于声明了一个全局变量。若不打算公开这个常量,就放在实现文件里,放在@implementation之前。static修饰符意味着变量仅在定义此变量的编译单元可见
对于外界可见的常值变量,一般需放到全局符号表
定义方式如下
#header fileextern NSString *const EOCStringConstant;# implementation fileNSString *const EOCStringConstant = @"value";#在头文件声明,在实现文件中定义
只能有一个,为了避免名称冲突,最好是用与之相关的类名做前缀
- 不要用预处理指令定义常量,因为这样的常量不含类型信息。编译器只是查找,替换。
- 在实现文件使用static const定义只在编译单元内可见的常量,这类常量不在全局符号表中,所以无须为其名称添加前缀。
- 头文件中使用extern来声明全局常量,并在相关实现文件中定义其值,会出现在全局符号表中,所以通常用类名做前缀。
用枚举表示状态、选项、状态码
Object-C采用C++11标准,枚举是强类型(strong type)
示例如下:
enum EOCConnectionState{ EOCConnectionStateDisconnected, EOCConnectionStateConnecting, EOCConnectionStateConnected,};typedef enum EOCConnectionState EOCConnectionState;#使用EOCConnectionState state = EOCConnectionStateDisconnected;
可以指明用何种底层数据来保存枚举类型的变量,所以可以使用向前声明枚举变量了。
用法如下:
enum EOCConnectionState: NSInteger {...}#使用向前声明时指定数据类型enum EOCConnectionState: NSInteger;#不使用编译器所分配的序号,手工指定某个枚举成员所对应的值enum EOCConnectionState{ EOCConnectionStateDisconnected = 1, EOCConnectionStateConnecting, EOCConnectionStateConnected,};//接下来的几个枚举值会在上一个基础上递增1
另一个例子就是定义选项,如果选项之间可以组合,则考虑用按位或操作符
具体可以参考UIViewAutoresizing
Foundation框架定义了一些辅助宏,用这些宏可以指定枚举值的底层数据类型,并且具备向后兼容能力。
用法如下:
typedef NS_ENUM(NSUInteger, EOCConnectionState) { EOCConnectionStateDisconnected, EOCConnectionStateConnected, EOCConnectionStateConnecting,};typedef NS_OPTIONS(NSUInteger, EOCPermittedDirection) { EOCPermittedDirectionUp = 1 << 0, EOCPermittedDirectionDown = 1 << 1, EOCPermittedDirectionLeft = 1 << 2, EOCPermittedDirectionRight = 1 << 3,};
凡是需要按位或操作来组合的枚举都应使用NS_OPTIONS宏,不需要互相组合的,使用NS_ENUM来定义
另外,switch来处理枚举时,最好不要用default,这样当加入新的状态时,编译器会发出警告,保证switch处理了所有的样式
总结
- 用枚举来表示状态机的状态、传递给方法的选项以及状态码等值,给这些值起个易懂的名字。
- 如果传递给某个方法的选项表示为枚举,而多个选项可以同时使用,那么就将各选项的值定义为2的幂,以便可以通过按位或操作将其组合起来。
- 用NS_ENUM,NS_OPTIONS宏来定义枚举类型,并指明其底层数据类型,这样保证了向后兼容。
- 在处理枚举类型的switch语句中,不要实现default分支,这样可以保证能处理所有的类型。
- Effective Object C 2.0——熟悉Object-C
- Effective Object-C 2.0
- Effective Object-c 2.0 读书笔记
- Effective Objective-C 2.0: Object Equality
- Effective Object-C 2.0 学习(一)
- Effective Object-c 2.0 读书笔记 (2)
- Effective Object-C之属性
- Object—C
- Object-C—字符串
- Object—C基础
- Effective Object C 2.0——对象、消息和运行期
- Effective Objective-C 2.0:Item 14 Class Object
- Effective Object-C 2.0 第一章(条目1和2)
- Effective Object-C 2.0 第一章(条目3)
- Effective Object-C 2.0 第一章(条目5)
- Effective Object-C 2.0 第一章(条目4)
- Effective Objc : Object-C 中 @property 详解
- Object-C 基础之0 — object c简介
- Android项目开发总结(二)-- 架构篇
- LintCode统计前面比自己小的数的个数(线段树)
- Git 设置不需要用户名、密码直接push的操作
- 初步理解MVC与MVP
- Centos下安装python2.7 安装工具
- Effective Object C 2.0——熟悉Object-C
- 后及性、无前溯性与无后效性——马尔可夫过程“无后效性”回溯谈
- pcl使用迭代的最近的点
- 一种查看chromium代码两任何两个版本之间修改Log的方法
- 模版--两圆相交部分面积
- 如何获取到Hadoop集群的个数
- SpringMvc - 用户注册自动生成默认头像深色底/浅色字工具类实现
- ELK实战-Logstash:监控日志文件
- 根据树的前序遍历、中序遍历、后序遍历中的两种遍历求第三种遍历结果