iOS应用开发最佳实践系列一:编写高质量的Objective-C代码

时间:2023-03-08 17:07:35
iOS应用开发最佳实践系列一:编写高质量的Objective-C代码

      本文由海水的味道编译整理,转载请注明译者和出处,请勿用于商业用途!

点标记语法

属性和幂等方法(多次调用和一次调用返回的结果相同)使用点标记语法访问,其他的情况使用方括号标记语法。

良好的风格:

view.backgroundColor = [UIColor orangeColor];

[UIApplication sharedApplication].delegate;

不良的风格:

[view setBackgroundColor:[UIColor orangeColor]];

UIApplication.sharedApplication.delegate;

间距

二元运算符和参数之间需要放置一个空格,一元运算符强制类型转换和参数之间不放置空格。关键字之后圆括号之前需要放置一个空格。

void *ptr = &value + 10 * 3;

NewType a = (NewType)b;

for (int i = 0; i < 10; i++) {

doCoolThings();

}

数组和字典类型的字面值的方括号两边各放置一个空格。

NSArray *theShit = @[ @1, @2, @3 ];

字典字面值的键和冒号之间没有空格,冒号和值之间有一个空格。

NSDictionary *keyedShit = @{ GHDidCreateStyleGuide: @YES };

C函数声明中,左括号的前面不保留空格,并且函数名应该像类一样带有命名空间标识。

良好的风格:

void RNCwesomeFunction(BOOL hasSomeArgs);

长的字面值应被拆分为多行。

良好的风格:

NSArray *theShit = @[

@"Got some long string objects in here.",

[AndSomeModelObjects too],

@"Moar strings."

];

NSDictionary *keyedShit = @{

@"this.key": @"corresponds to this value",

@"otherKey": @"remoteData.payload",

@"some": @"more",

@"JSON": @"keys",

@"and": @"stuff",

};

每一行代码使用4个空格缩进。不使用tab缩进。下图是在Xcode的Preferences进行缩进设置的截图。

iOS应用开发最佳实践系列一:编写高质量的Objective-C代码

iOS应用开发最佳实践系列一:编写高质量的Objective-C代码

方法签名以及其他关键字(if/else/switch/while等)后面跟随的左花括号总是和语句出现于同一行,而右花括号独占一行。

良好的风格:

if (user.isHappy) {

//Do something

}

else {

//Do something else

}

如果一个方法内有多个功能区域,可以使用空行分隔功能区域。

每一行代码不要超过100个字符。

每一个方法之前都有一个99字符宽的注释行,注释行相对于使用空行更能提高代码的辨识度,当一行代码很长的时候,注释行也起到了越界检测的作用。注释行:

///////////////////////////////////////////////////////////////////////////////////////////////////

条件语句

当需要满足一定条件时才执行某项操作时,最左边缘应该是愉快路径代码。不要将愉快路径代码内嵌到if语句中。多个return是正常合理的。

良好的风格做法:

- (void)someMethod {

if (![someOther boolValue]) {

return;

}

//Do something important

}

不良的风格:

- (void)someMethod {

if ([someOther boolValue]) {

//Do something important

}

}

所有的逻辑块必须使用花括号包围,即使条件体只需编写一行代码也必须使用花括号。

良好的风格做法:

if (!error) {

return success;

}

不良的风格:

if (!error)

return success;

或:

if (!error) return success;

三元运算符

长的三元运算符应使用圆括号括起来。三元运算符仅用于赋值和做参数。

Blah *a = (stuff == thing ? foo : bar);

合并的nil三元运算符应该尽量避免。

不良的风格:

Blah *b = thingThatCouldBeNil ?: defaultValue;

多分支条件应该使用if语句或重构为实例变量。

良好的风格:

result = a > b ? x : y;

不良的风格:

result = a > b ? x = c > d ? c : d : y;

异常和错误处理

不要在流控制语句中使用异常(NSException)。

异常仅用于表明程序员的错误。

为了表明一个错误,使用NSError *。

当一个方法通过引用返回一个错误参数,应该检测返回值的状态,而不是错误参数的状态。

良好的风格:

NSError *error;

if (![self trySomethingWithError:&error]) {

// Handle Error

}

不良的风格:

NSError *error;

[self trySomethingWithError:&error];

if (error) {

// Handle Error

}

在方法执行成功的情况下赋值非Null值给错误参数,会使路径跳转到假条件分支(随后程序奔溃)。

代理

除了继承一个类或实现一个协议,否则在头文件中仅使用类声明@class指令,不用#import导入类头文件。

如果一个delegate只有几个方法,比如只是提交和取消,推荐使用block编写动作响应代码。

使用block还是delegate编写回调代码遵循以下几点:(详见参考链接[8])

Ø   如果对象存在多个不同事件,则应该使用代理模式编写各事件的处理代码

Ø   如果对象是单例,应该使用block,而不是代理。

Ø   如果对象是为了其他的信息而进行回调,则使用代理。

Ø   代理更多的是面向于过程,而block则更多的面向于结果。

由于代理方法的声明一般都很长,所以必须将代理对象和其他的协议对象放在实例变量定义的下面,否则实例变量定义的对齐方式将会被打乱掉。

当需要实现多个协议的时候,将每一个协议名拆分到单独的行。

良好的风格:

@interface CustomModelViewController : TTViewController <

TTModelDelegate,

TTURLRequestDelegate

> {

方法

一个方法的命名首先描述返回什么,接着是什么情况下被返回。方法签名中冒号的前面描述传入参数的类型。以下类方法和实例方法命名的格式语法:

[object/class thing+而BOOL类型是8位的unsigned int,即BOOL的值不仅仅是1或0。

良好的风格:

if (!someObject) {

}

不良的风格:

if (someObject == nil) {

}

对于一个BOOL值:两种最佳实践:

if (isAwesome)

if (![someObject boolValue])

不良的风格:

if ([someObject boolValue] == NO)

if (isAwesome == YES) // Never do this.

如果一个BOOL类型的属性名是一个形容词,忽略属性名的“is”前缀是允许的,但需要为访问器指定约定的方法名,比如:

@property (assign, getter=isEditable) BOOL editable;

单例

应该使用线程安全的模式创建共享的单例实例。

+ (instancetype)sharedInstance {

static id sharedInstance = nil;

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

sharedInstance = [[self alloc] init];

});

return sharedInstance;

}

Normal
0

10 pt
0
2

false
false
false

EN-US
ZH-CN
X-NONE

$([{£¥·‘“〈《「『【〔〖〝﹙﹛﹝$(.[{£¥
!%),.:;>?]}¢¨°·ˇˉ―‖’”…‰′″›℃∶、。〃〉》」』】〕〗〞︶︺︾﹀﹄﹚﹜﹞!"%'),.:;?]`|}~¢

/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";}

单例的另一种做法,利用+ initialize方法。(JSONModel源码43行:http://t.cn/8F7uBF4):

static JSONAPI*
sharedInstance = nil;

+ (void)initialize {

static dispatch_once_t once;

dispatch_once(&once, ^{

sharedInstance = [[JSONAPI alloc]
init];

});

}

附录

Xcode主题

大部分的开发者都使用Xcode默认的字体颜色主题,其实好的主题不仅能提高源代码的辨识度,同时也增添了编码的乐趣。以下是二款Xcode字体颜色主题链接:

https://github.com/vinhnx/Ciapre-Xcode-theme

https://github.com/tursunovic/xcode-themes

代码片段

熟练使用代码片段库可以提高编码的速度。Xcode4中,打开一个项目并让右侧编辑区可视,然后点击右侧底部面板的第四个{}图标,打开代码片段库,你可以将常用的代码拖入其中。以下是一个最新的开源代码片段库链接:

https://github.com/mattt/Xcode-Snippets

在code snippet library新建如下代码,设定一个类似vci(view controller initialize含义)自动提示快捷键。当开始编写ViewController或View时,键入vci,将相应的代码填入对应的位置。

#pragma mark - init
Method

填入init,initWithFrame等方法

#pragma mark- View
Life Cycle

填入viewdidload,viewdidappear等方法

#pragma mark-
Override Parent Methods

填入updateViewConstraints,updateConstraint, prepareForSegue等方法

#pragma mark-
SubViews Configuration

填入configureSubViews,configureTableView等方法,这里的方法在init方法或view
life cycle被调用

#pragma mark- Actions

填入-(IBAction)action:(id)sender和[self
addtarget:self action:@selector(action:)]动作指向的方法

#pragma mark- Public
Methods

填入在.h外暴露的方法

#pragma mark- Private
Methods

填入.m文件内部调用的方法

#pragma mark-
Delegate,DataSource, Callback Method

填入tableview,scrollview等代理方法

#pragma mark- Getter
Setter

填入对@property初始化的方法

#pragma mark- Helper
Method

填入一些帮助方法,如果使用扩展实现帮助方法不合适,则将帮助方法填在这里

#pragma mark
Temporary Area

填入一些你需要删除,或者不确定后面需不需要用,或者写一写备注之类的,类似代码回收站含义


参考链接

[1] 《NYTimes Objective-C Style Guide》 https://github.com/NYTimes/objective-c-style-guide

[2] 《Coding Guidelines for Cocoa》https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/APIAbbreviations.html

[3] 《iOS-view-frame-builder》https://github.com/rsobik/ios-view-frame-builder/commit/0fa2d81762bc21619b1503d34b7d67160f4678f8

[4] 《Cocoa Style for Objective-C: Part Ihttp://cocoadevcentral.com/articles/000082.php

[5] 《Cocoa Style for Objective-C: Part II》http://cocoadevcentral.com/articles/000083.php

[6] 《objective-c-conventionsI》https://github.com/github/objective-c-conventions

[7] 《The official raywenderlich.com Objective-C style guide.》https://github.com/raywenderlich/objective-c-style-guide#cgrect-functions

[8] 《Blocks or Delegation》http://stablekernel.com/blog/blocks-or-delegation/

文档修订历史

时间

备注

2015-10-18

添加code-snippet示例

2014-01-16

完善代理、条件语句、单例

2013-09-07

编写高质量的Objective-C代码

如果喜欢此文,记得点击文章下方的推荐,以让更多的人有所收获。

文章中如有错误或不当之处望不吝指出,谢谢!

我的邮箱和微博: xdreamarshal@gmail.com, http://weibo.com/xdream86

本文的pdf下载地址