Effective Objective-C 2.0 读书笔记一

这本书中的内容都是精华,文章也很简洁了,但是我要让他更简洁更易懂,由于我是一个初学者,所以就用我自己能够理解的直白话语总结一下这52个方法,希望再看的时候理解起来不用这么麻烦,好的,马上开始吧!

第一章 熟悉Objective-C

Objective-C(以下简称OC)是C语言的超集,是在C语言的基础上添加了面向对象特性

1. 了解Objective-C的起源

首先,OC是一门面向对象语言,但是语法和其他的面向对象语言有很大差异,运用大量的中括号,这让写习惯其他语言的人感觉很别扭,不过,什么东西都是,习惯就好。
OC使用的是“消息结构”(messaging structure)而不是“函数调用”(function calling)是由Smalltalk演化而来,Smalltalk是消息型语言的鼻祖。好的,那么解释一下什么是消息型语言,函数调用相信大家都理解,消息结构语言,是运行时所执行的代码是由运行环境决定的,而不是由编译器决定的,这就决定了OC是一门动态型语言,也就是人们说的运行时(runtime),这个怎么理解呢,就是你先声明一下你是一个类型,但是具体是什么类型,等真正运行的时候在确定,好了,就到这,说多了我也不懂。
下面说一下OC的内存管理,OC采用引用计数机制,就是你调用一次对象,我就把引用计数加一,销毁一次就减一,当引用计数为0的时候,系统就会把这个对象销毁,现在在ARC环境下,计数是由编译器帮我们管理的,所以我们很幸运,不用太纠结于这个地方。
C语言中*代表的是指针,OC中指针是用来指示对象的,所以声明一个变量语法是:

NSString *aString = @"The string"

OC中对象都是分配在堆内存上的,所以aString这个指针指向堆内存,在堆内存中有一个NSString对象,这也就是说,如果我们再创建一个变量,让其指向同一个内存地址:

NSString *aString = @"The string";
NSString *bString = aString;

这样我们就创建了指向同一个内存地址的两个指针,而不是拷贝该对象,在OC中我们有时候会看到定义一个变量不带*,这种变量有可能使用栈内存,例如CGRect,这种变量保存的不是OC对象,而是系统框架的结构体,创建这种结构体比创建对象节省内存开销。

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

OC编写类的标准方式是文件名做为类名,同事生成一个.m文件和一个.h文件,一般情况下.h文件负责对外提供接口,.m文件负责内部实现,当在一个类中需要引入其他类的时候,我们就要通过#import导入其他头文件,其实有很多时候我们在.h中引入头文件是不需要的,我们只要用@class声明一个类就可以了,我下面用例子说一下这么做的好处,现在有三个类

one.h
two.h
three.h

我们在two类中需要one类,我们可以这样引入

two.h
#import "one.h"

当我们在three类中需要two类的时候我们这样引入

three.h
#import "two.h"

那么问题来了,这样做我们在three类中引入two类的时候间接引入了one类,而在three类中我们可能不需要one类,这样我们在编译的时候会增加编译时间(注意:只是增加编译时间,和运行时间没有关系),虽然这样做不会增加我们的运行时间,但是当我们间接引入过多头文件的时候,编译时间会大大增加,并且影响代码的阅读性,这个时候@class就很好用了,我们只要这样写:

two.h
@class one;
three.h
@class two;

这样就可以避免在three类引入two类的时候间接引入one类了
这里的@class只是声明一个类,而不是把类的所有细节引入,当我们要用的类的属性、方法的时候,我们只要在.m中引入头文件就可以了,这样做可以提高我们的编译效率,并且可以避免循环引用,虽然#import可以避免我们循环引用,但是在a类引用b类同时b类又引用a类的时候还是有一个类无法被正确编译,另外这样做还可以降低类之间的耦合。
有时候我们不得不引入头文件,例如某个类要继承一个父类,这个时候必须引入父类头文件,还有我们要遵从某个协议的时候(比如代理协议),此时我们就必须要引入头文件,来知道细节。
一般我们解决协议的引用,都是把协议放在分类里(class-continuation category)

3. 多用字面量语法

字面量语法是一种“语法糖”,OC中常用的字面量:

字面量类型 实现方式
字符串 NSString *aString = @"string"
数值 NSNumber *aNumber = @1
数组 NSArray *aArray = @[@"object1", @"object2", @"object3"]
字典 NSDictionary *aDictionary = @{@"key1":@"value1", @"key2":@"value2", @"key3":@"value3"}

我们可以看到,字面量语法简洁易懂,字面量语法的另一个好处就是当我们输入的值为nil的时候编译器会提示错误,这样可以确保我们得到想要的字典或数组,如果我们用方法生成数组或字典可能会有不一样的结果,例如:

id object1 = @"string1";
id object2 = nil;
id object3 = @"string3";
NSArray *aArray = [NSArray arrayWithObjects:object1, object2, object3, nil];

这样创建出来的数组实际上只有一个对象,因为object2是nil,如果用字面量创建,会直接报错
字面量的局限性就是创建的数组和字典都是不可变的,还有除了字符串以外,创建的对象都必须属于Foundation框架

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

我们在定义一个常量的时候通常会用#define,例如:

#define kBottomMargin 25

首先说一下这么做坏处,这样定义首先没有描述常量类型,另外如果这样定义在.h文件中,所有引用这个.h文件的代码都会把kBottomMargin替换为25,我们应尽量避免这样定义。
替代方法:

static const NSUInteger kBottomMargin = 25;

这样定义一个常量好处是我们确定了常量类型,并且,当我们试图修改这个常量的时候,编译器会报错,因为有const修饰。
这样定义,我们解决了类型的问题,但是如果放在.h文件中定义的时候,还是无法消除引用的问题,而实际上我们有的时候要把这种常量暴露在外面,供别人使用(例如通知名称),这时候我们可以用另外一种方法:
在.h文件中:

extern NSString *const kNotifictionName;

在.m中

NSString* const kNotifictionName = @"kNotifictionName";

这样就圆满解决了我们的问题,所以我们以后可以放弃用#define定义一个常量了,同时我们也要避免在.h文件中用static const来定义一个常量

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

枚举的好处相信大家都知道,基本的写法大家也都会,这里提一下大家可能忽略的地方:

  • 编译器为枚举值分配独有的编号,从0开始,然而这个初始值我们可以自己设定,只要设定第一个,后面的会自动加1
  • 我们可以自行设定保存枚举类型变量的“底层数据类型”
enum buttonState: NSInteger{/* ... */};
  • 系统为我们提供了两种宏创建枚举,分别是定义普通枚举的宏NS_ENUM和创建可选多项可选类型的枚举宏NS_OPTIONS
    例子:
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
    UIViewAnimationTransitionNone,
    UIViewAnimationTransitionFlipFromLeft,
    UIViewAnimationTransitionFlipFromRight,
    UIViewAnimationTransitionCurlUp,
    UIViewAnimationTransitionCurlDown,
};
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
  • switch语句中,若用枚举来定义状态机,最好不要有default分支,这样做是为了确保switch语句能处理所有状态
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容