《Objective-C 2.0编写高质量iOS与OS X代码的52个有效方法》---学习笔记(1-10)

前言

这本书大致看过一次,但没有做笔记。
不做笔记,总觉得没学过。。。
那么,再看一遍,做下笔记


1. 了解Objective-C语言的起源

OC为C语言添加了面向对象特性,是其超集。OC使用动态绑定的消息结构,也就是说,在运行时才会检查对象类型。

2. 在类的头文件中尽量 少 引入其他头文件

在.h文件中,需要引入其他类A时,如果并不需要知道类A的具体细节,只需要知道有一个类名叫A即可,那么,可以使用@class A;,然后在.m文件中,真正用到类A时,再在头部引入:#import "A.h";

将引入头文件的时机尽量延后,只在确有需要时才引入,这样可以减少类的使用者所需要引入的头文件数量。
引入A.h的时候,会将A里面所有的内容都引入进去,这样会引入许多用不到的内容,增加编译时间

问题是,在.h中使用@class,在.m中引入A,那么A的内容同样全部引入到了.m文件中
还有个在实际开发中的问题,增加了代码量,虽然是多了一行,愿意写不写,也是个问题。

3. 多用字面量语法,少用与之等价的方法

字符串字面量:NSString *someString = @"this is a string";
字面数值:NSNumber *someNumber = @1;
此外,还有:字面量数组、字面量字典

使用字面量语法创建出来的 字符串、数组、字典 对象都是不可变的。
若想使用可变版本的对象,则需要复制一份:
NSMutableArray *mutable = [@[@1, @2, @3, @4, @5] mutableCopy];

应该通过取下标操作来访问数组下标 或 字典中的键所对应的元素

4. 多用类型常量,少用#define预处理指令

多使用:static const NSTimerInterval kAnimationDuration = 0.3;,少用:#define ANIMATION_DURATION 0.3

  • 使用static const常量,带有类型信息

常量命名建议方法:

  • 若常量局限在某个.m文件之内,则在前面加上字母k
  • 若常量类之外可见,则通常以类名为前缀。

编译器每接收到一个“编译单元”(以.m为后缀名),就会输出一份“目标文件”(object file)

在定义通知的“全局符号表”(global symbol table)中,使用:
.h中:
extern NSString *const XXXNAME;

.m中:
NSString *const XXXNAME = @"VALUE";

在头文件(.h)文件中“声明”
在实现文件(.m)文件中“定义”

5. 用枚举表示状态、选项、状态码

某个对象所经历的各种状态就可以定义为一个简单的枚举集(enumeration set)

在定义选项的时候,特别是这些选项可以彼此组合的时候,此时,更适合用enum
组合这种,只要使用了位运算操作:<< |


对象、消息、运行期

6. 理解“属性”这一概念

“属性”(property)是OC的一项特性,用于封装对象中的数据。
访问属性,可以使用“点语法”,编译器会把“点语法”转换为对存取方法的调用

使用@property属性,编译器做的事情:

  • 自动生成setter方法、getter方法
  • 自动添加适当类型的实例变量,并在属性名前面加下划线,作为实例变量的名字

@dynamic关键字会告诉编译器:

  • 不要自动创建实现属性所用的实例变量
  • 不要为其创建存取方法

属性特质

@property (nonatomic, readwrite, copy) NSString *firstName;
属性拥有四类特质:
原子性、读写权限、内存管理语义、方法名

原子性

默认情况下,由编译器所合成的方法会通过锁定机制确保其原子性(atomic)
但,开销比较大,因此,异步不使用atomic

nonatomic,不使用同步锁

读写权限

readwrite,默认方法,拥有getter和setter方法
readonly,只有getter方法

内存管理语义

属性用于封装数据,而数据则要有“具体的所有权语义”

  • assign: 针对“纯量类型”(CGFloat 或 NSInteger等)的简单赋值
  • strong: 此特质表明该属性定义了一种“拥有关系”。为这种属性设置新值时,设置方法会先保留新值,并释放旧值,然后再将新值设置上去
- (void)setFoo:(id)foo {
	[foo retain];//保留新值
	[_foo release];//释放旧值
	_foo = foo;//更新实例变量
}
  • weak: 此特质表明该属性定义了一种“非拥有关系”。在属性所指的对象遭到摧毁时,属性值也会清空(nil out)
  • unsafe_unretained: 与assign相同,但也适用于“对象类型”,表示“非拥有关系”,当目标对象摧毁时,不会自动清空
  • copy: 与strong类似。然而设置方法并不保留新值,而是将其copy

方法名

@property (nonatomic, getter = isOn) BOOL on;

7. 在对象内部尽量直接访问实例变量

在对象之外访问实例变量时,总是应该通过属性来访问。
在对象之内,有“通过属性访问”与“直接访问”两种方法,本书建议

  • 在读取实例变量的时候,采用“直接访问“

  • 在设置实例变量的时候,采用”通过属性访问“

  • 直接访问实例变量不经过”方法派发“(method dispatch),编译器所生成的代码会直接访问保存对象实例变量的那块内存,所以速度快

  • 直接访问实例变量,不会触发KVO

  • 在初始化方法中,总是 直接访问实例变量

  • 在懒加载中,必须通过setter方法访问属性,不能通过下划线直接访问

  • 在dealloc方法中,直接通过实例变量来读写数据

8. 理解”对象等同性“这一概念

”等同性“(equality),来比较对象

”==“操作符比较的是两个指针本身,指针相等才返回YES

NSObject协议中,有一个”isEqual“方法:该方法首先会判断是否为同一个类,然后再来判断两个对象的等同性。此等同性,指的是:指针值完全相等

NSObject里面有两个重要的方法:
在这里插入图片描述
若两对象相等,则其哈希码也相等。
但两个哈希码相同的对象却未必相等。

而NSString就厉害了,有个"isEqualToString"方法,直接判断两个字符串内容是否相同
NSString中,isEqualToString比isEqual快,因为后面还需要执行额外步骤,因为它不知道受测对象的类型

同样,NSArray与NSDictionary类也有特殊的等同性判定方法:
isEqualToArray:isEqualToDictionary:
使用这两个方法,需要保证所比较类型为对应正确类型

9. 以“类簇模式”隐藏实现细节

其实,有点多态的意思

NSArray、NSDictionary都是类簇,是基类。也叫做:抽象基类

  • 子类应该继承自类簇中的抽象基类
  • 子类应该定义自己的数据存储方式
    NSArray本身只是包在其他隐藏对象外面的壳,它仅仅定义了所有数组都需具备的一些接口。
  • 子类应当覆写超类文档中指明需要覆写的方法

10. 在既有类中使用关联对象存放自定义数据

关联对象(Associated Object)

  • 可以给某对象关联许多其他对象,这些对象通过“键”来区分。
  • 可以通过“关联对象”机制,来把两个对象连起来
  • 在设置关联对象值时,通常使用静态全局变量做键

关联对象的几个重要方法:
void objc_setAssociatedObject()
id objc_getAssociatedObject()
void objc_removeAssociatedObjects()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值