Effective Objective-C 2.0笔记

第一条:了解Objective-C语言的起源

1.Objective-C语言的对象所占内存总是分配在“堆空间”中。
2.分配在堆中的内存必须直接管理,而分配在栈上用于保存变量的内存则会在其栈帧弹出时自动清理。
3.基本类型也被存放在栈空间。

屏幕快照 2017-03-18 上午11.44.43.png

第2条:在类的头文件中尽量少引用其他头文件

1.当一个类作为另一个类的属性的类型时,只需声明

@class className

有两个好处:
(1) 减少编译时间
(2)解决了两个雷相互引用的问题。
如果在各自头文件中引入对方的头文件,则会导致“循环引用”。当解析其中一个头文件时,编译器会发现它引入了另一个头文件,而那个头文件回过头来引用了第一个头文件。使用#import而非#include指令虽然不会导致死循环,但这意味着两个类里有一个无法被正确编译。
2.最好把协议单独放在一个头文件中。
3.委托协议就不能单独写一个头文件了。此时最好能在实现文件中声明此类实现了委托协议,并把这段代码放到“class-continuation”分类里。这样的话,只要在实现文件中引入包含委托协议的头文件即可。

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

1.字面量字符串

NSString *someString = @"Effective Objective-C 2.0";

2.字面数值

NSNumber *intNumber = @1;
NSNumber *floatNumber = @2.5f;
NSNumber *doubleNumber = @3.14159
NSNumber *boolNumber = @YES;
NSNumber *charNmuber = @'a';

int x = 5;
float y = 6.32f;
NSNumber *expressionNumber = @(x * y);

3.字面量数组

NSArray *animals = @[@"cat",@"dog",@"mouse",@"badger"];
NSString *dog = animals[1];

4.字面量字典

NSDictionary *personData = @{@"firstName":@"Matt",@"lastName":@"Galloway",@"age":@28};
NSString *lastName = personData[@"lastName"];

与数组一样,用字面量语法创建字典时也有个问题,那就是一旦有值为nil,便会抛出异常
5.可变数组与字典

mutableArray[1] = @"dog";
mutableDictionary[@"lastName"] = @"Galloway";

使用字面量语法创建出来的字符串、数组、字典对象都是不可变的。若想要可变版本的对象,则需复制一份

NSMutableArray *mutable = [@[@1,@2,@3,@4,@5]  mutableCopy];

第4条:多用类型变量,少用#define预处理指令

1.用以下方式定义的变量包含类型信息,其好处是清楚地描述了常量的含义。

static const NSTimeInterval kAnimationDuration = 0.3;

如果试图修改由const修饰符所声明的变量,那么编译器就会报错。而static修饰符则意味着改变量仅在定义此变量的编译单元中可见(.m文件中)。
2.如果需要对外公开某个变量,应该这样定义:

// In the header file
extern NSString *const EOCStringConstant;

// In the implementation file
NSString *const EOCStringConstant = @"VALUE";

这样定义常量优于使用#define预处理指令,因为编译器会确保常量值不变。一旦在.m中定义好,即可随处使用。而采用预处理指定所定义的常量可能会无意中遭人修改,从而导致应用程序各个部分所使用的值互不相同。

第5条:用枚举表示状态、选项、状态码

1.枚举只是一种常量命名方式,某个对象所经历的各种状态就可以定义为一个简单的枚举集。

enum EOConnectionState {
        EOConnectionStateDisconnected,
        EOConnectionStateConnecting,
        EOConnectionStateConnected,
};

// 定义变量的方式
enum  EOConnectionState state =  EOConnectionStateDisconnected,

若是每次不用敲入enum而只需写EOConnectionState就好了。要想这样做,则需使用typedef关键字重新定义枚举类型:

enum EOConnectionState {
        EOConnectionStateDisconnected,
        EOConnectionStateConnecting,
        EOConnectionStateConnected,
};
typedef enum EOConnectionState EOConnectionState;
// 定义变量的方式
enum  EOConnectionState state =  EOConnectionStateDisconnected,

2.可以指明用何种“底层数据类型”来保存枚举类型的变量。这样做的好处是,可以向前生命枚举变量了。若不指定底层数据类型,则无法向前声明枚举类型,因为编译器不清楚底层数据类型的大小,所以在用到此类枚举时,也就不知道究竟该给变量分配多少空间。
指定底层数据类型所用的语法是:

enum EOCConectionStateConnectionState :NSInteger  { /*...*/};

在向前声明时指定底层数据类型:

enum EOCConectionStateConnectionState :NSInteger;

3.不使用编译器所分配的序号,而是手工指定某个枚举成员所对应的值。

enum EOConnectionState {
        EOConnectionStateDisconnected = 1,
        EOConnectionStateConnecting,     //  2
        EOConnectionStateConnected,     //  3
};

4.定义选项的时候,若这些选项可以彼此组合,各选项可通过“按位或操作符”来组合。

enum UIViewAutoresizing {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

因为每个枚举值所对应的二进制表示中,只有一个二进制位的值是1。用“按位与操作符”即可判断出是否已启用某个选项:

enum UIViewAutoresizing resizing =  UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
if(resizing & UIViewAutoresizingFlexibleWidth){
        // UIViewAutoresizingFlexibleWidth is set
}

5.凡是需要按位或操作来组合的枚举都应使用NS_OPTIONS定义。若是枚举不需要相互组合,则应使用NS_ENUM来定义。

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
};

以上代码等价于

屏幕快照 2017-03-19 上午10.10.28.png

6.枚举用在switch语句里,最好不要有default分支。

屏幕快照 2017-03-19 上午10.12.48.png

第6条:理解属性这一概念

1.在OC中,把实例变量当做一种存储偏移量所用的“特殊变量”,交由“类对象”保管。偏移量会在运行期查找,如果类的定义变了,那么存储的偏移量也就变了,这样的话,无论何时访问实例变量,总能使用正确的偏移量。
2.@synthesize和@dynamic

@implementation EOCPerson
@synthesize firstName = _myFirstName;
@synthesize lastName = _myLastName;
@end

上述语法会将生成的实例变量名为为_myFirstName与_myLastName,而不再使用默认的名字。
使用@dynamic关键字,它会告诉编译器:不要自动创建实现属性所用的实例变量,也不要为其创建存取方法。而且,在编译访问属性的代码时,即使编译器发现没有定义存取方法,也不会报错,它相信这些方法能在运行期找到。
3.具备readonly属性的属性仅拥有获取方法,只有当改属性由@synthesize实现时,编译器才会为其合成获取方法。你可以用此特质把某个属性对外公开为只读属性,然后在“class-continuation分类”中将其重新定义为读写属性。
4.内存管理语义

  • assign “设置方法”只会执行针对“纯量类型”(scalar type,例如CGFloat或NSInteger等)的简单赋值操作。
  • strong 此特质表明该属性定义了一种“拥有关系”。为这种属性设置新值时,设置方法会先保留新值,并释放旧值,然后再将新值设置上去。
  • weak 此特质表明该属性定义了一种“非拥有关系”。为这种属性赋新值时,设置方法既不保留新值,也不释放旧值。此特质同assign类似,然而在属性所指的对象遭到摧毁时,属性值也会清空。
  • unsafe_unretained 此特质的语义和assign相同,但是它适用于“对象类型”,该特质表达一种“非拥有关系”,当目标对象遭到摧毁时,属性值不会自动清空,这一点与weak有区别。
  • copy 此特质所表达的所属关系与strong类似,然而设置方法并不保留新值,而是将其“拷贝”。只要实现属性所用的对象是“可变的”,就应该在设置新属性值时拷贝一份。

第7条:在对象内部尽量直接访问实例变量

在写入实例变量时,通过其设置方法来做,而在读取实例变量时,则直接访问之。此办法既能提高读取操作的速度,又能控制对属性的写入操作。

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

推荐阅读更多精彩内容