《Effective Objective-C 2.0编写高质量iOS与OS X代码的52个方法》要点回顾(一)第一章 熟悉 Objective-C

1. 了解OC语言的起源

知识点

  1. OC: 消息型类型,使用消息结构,其运行时所应执行的代码由 运行环境 决定;
  2. 而使用函数调用的语言,则由 编译器 决定。
  3. 对象所占内存总是分配在 堆空间,而绝不会在栈上。
  4. 上保存的是指向对象的指针。
  5. 定义里不含 “ * ” 的变量(非对象类型),可能会被分配到 栈 上,如CGRect。它是C 结构体。

要点总结

  • Objective-C 为 C 语言添加了 面向对象 的特性,是其超集。Objective-C使用 动态绑定的消息结构 。所以,在运行时 才会检查对象类型。接收一条消息之后,究竟应执行何种代码,由运行时环境决定,而非编译器。

  • 理解C语言的核心概念(重点是内存模型指针)有助于写好OC程序。

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

想要在一个文件中引入另一个(如Model:Person.h)类,且只需要知道类名,可以:

//#import "Person.h"
@class Person;

这种写法,叫“向前声明”该类。总结:

除非有必要,否则不要引入头文件。一般来说,应在某个类的 (xxxx.h)头文件 中使用 向前声明 来提及别的类,并在 (xxxx.m)实现文件 中引入那些类的头文件。这样做 可以尽量降低类之间的耦合(coupling)

有时无法使用向前声明,如声明某个类遵循一项协议。这种情况下,尽量把 “该类遵循某协议” 的这条声明移至 “class-continuation分类” 中。如果不行的话,就把协议单独放在一个头文件中,然后将其引入。见27条

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

知识点

  1. 使用字面量语法(Literal syntax)可以缩短源代码长度,使之更为易读。如
  • 字面数值
/** 1 */
NSString *someString1 = [[NSString alloc] initWithString:@"I'm wanazen"];
//可简写为:
NSString *someString2 = @"I'm wanazen";

/** 2 */
NSNumber *someNumber = [NSNumber numberWithInt:1];
//可简写为:
NSNumber *intNumber = @1;
NSNumber *doubleNumber = @3.14159;
NSNumber *boolNumber = @YES;
NSNumber *charNumber = @'a';

int x = 5;
float y = 8.99f
NSNumber *expressionNumber = @(x * y) ;
  • 字面量数组
/** 创建 */
NSArray *animals = [NSArray arrayWithObjects:@"cat", @"dog", @"mouse", nil];
//可简写成
NSArray *animalsNew = @[@"cat", @"dog", @"mouse"];

/** 取值 */
NSString *cat = [animals objectAtIndex:0];
//可简写为
NSString *catNew = animalsNew[i];
  • 字面量字典
/** 创建 */
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:@"Wanazen",@"firstName", @"Lona", @"lastName", [NSNumber numberWithInt:2019], @"year"];
//可简写为
NSDictionary *dic2 = @[@"firstName":@"Wanazen", @"lastName":@"Lona", @"year":@2019];

/** 取值 */
NSString *firstName = [dic objectForKey:@"firstName"];
//可简写为
NSString *firstName2 = dic[@"firstName"];

//赋值操作可以写成字面量。
  1. 字面量语法实际上只是一种“语法糖”(syntax sugar),其效果等于是 先创建了一个对象,然后执行了那些简写之前的操作。
  2. 数组、字典等一旦有值为nil时,可能会抛出异常。
  3. 限制:除了字符串之外,所创建出来的对象必须属于Foundation框架才行。
  4. 使用字面量创建出来的字符串、数组、字典对象都是不可变的(immutable)。若想创建可变版本的对象,则需要复制一份。
//虽然会多调用一个方法,还要在创建一个对象,不过优大于劣
NSMutableArray *mutableArray = [[@1, @2, @3, @4] mutableCopy];

要点总结:

  • 应该 使用字面量语法来创建字符串、数值、数组、字典。与创建此类对象的常规方法相比,这么做更加简明扼要,易读

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

  • 用字面量语法创建数组或字典时,若值中有nil,则会抛出异常。因此,务必确保值里不含nil。

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

优化前的目标代码:

#define ANIMATION_DURATION 0.3
  1. 只在文件内(.m)使用 的写法:
/*
升级的写法. 
根据实际数据类型声明常量。
const:不允许修改。修改后编译器报错
static:局限在编译单元.m文件中
*/
static const NSTimInterval kAnimationDuration = 0.3;
  1. 在被引入的文件同样生效(对外开放) 的写法:
//在.h文件 - 声明

// LoginManager.h
#import <Foundation/Foundation.h>

extern NSString *const LoginManagerDidLoginNotification;

@interface LoginManager()
***
@end

//在.m文件 - 定义
// LoginManager.m

#import "LoginManager.h"

NSString *const LoginManagerDidLoginNotification = @"LoginManagerDidLoginNotification";

@implementation LoginManager
***
@end

常用的命名法:

  • 若常量局限在.m文件中,以 “k” 开头;
  • 在类之外可见,常以 类名 开头。
要点总结:
  • 不要使用预处理指令(#define)定义 常量 。这样定义出来的常量不含类型信息,编译器只是会在编译前据此执行查找和替换操作。即使有人重新定义了常量值,编译器也不会产生警告信息,这将导致应用程序中的常量值不一致。

  • 在实现文件(.m)中使用 static const 来定义 “只在编译单元内可见的常量”。由于此类常量不在全局符号表中,所以无需为其名称加前缀。

  • 在头文件中使用 extern 来声明全局常量,并在相关实现文件中定义其值。这种常量药出现在全局符号表中,所以其名称应加以区隔,通常用与之相关的类名做前缀。

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

由于 OC 基于 C 语言,所以 C 语言有的功能它都有。枚举(ENUM),是一种常量的命名方式。

/**
 C语言下的语法
*/
enum EOCConnectionStateConnectionState {
    EOCConnectionStateDisConnected = 1,
    EOCConnectionStateConnecting,
    EOCConnectionStateConnected,    
};

/**
 OC中
*/
typedef NS_ENUM(NSUInteger, EOCConnectionState) {
    EOCConnectionStateDisConnected,
    EOCConnectionStateConnecting,
    EOCConnectionStateConnected,    
};

//适用于 按位或操作来组合 的枚举
typedef NS_OPTIONS(NSUInteger, EOCPermittedDirection) {
    EOCPermittedDirectionUp = 1 << 0,
    EOCPermittedDirectionDown = 1 << 1,
    EOCPermittedDirectionLeft = 1 << 2,
    EOCPermittedDirectionRight = 1 << 3,
};
要点总结:
  • 应该用 枚举 表示状态机的状态传递给方法的选项以及状态码等值,给这些值起简单易懂的名字。

  • 如果把传递给 某个方法的选项 表示为枚举类型,而多个选项又可同时使用,那么就将各选项定义为2的幂对应的值,便于按 操作组合使用。

  • NS_ENUMNS_OPTIONS 宏 来定义枚举类型,并指明其底层数据类型。可以确保枚举是用开发者所选的底层数据类型实现的,而不会采用编译器所选的类型。

  • 在处理枚举类型的switch语句中不要出现 default分支 。这样在加入新枚举值之后,编译器会提示开发者:在switch语句中并未处理所有枚举。

系列文章

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

推荐阅读更多精彩内容