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语句能处理所有状态
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容