• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

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

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

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

点标记语法

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

良好的风格:

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进行缩进设置的截图。

 

 

方法签名以及其他关键字(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+condition];

[object/class thing+input:input];

[object/class thing+identifer:input];

Cocoa命名举例:

realPath    = [path     stringByExpandingTildeInPath];

fullString  = [string   stringByAppendingString:@"Extra Text"];

object      = [array    objectAtIndex:3];

// 类方法

newString   = [NSString stringWithFormat:@"%f",1.5];

newArray    = [NSArray  arrayWithObject:newString];

良好的自定义方法命名风格:

recipients  = [email    recipientsSortedByLastName];

newEmail    = [CDCEmail emailWithSubjectLine:@"Extra Text"];

emails      = [mailbox  messagesReceivedAfterDate:yesterdayDate];

当需要获取对象值的另一种类型的时候,方法命名的格式语法如下:

[object adjective+thing];

[object adjective+thing+condition];

[object adjective+thing+input:input];

良好的自定义方法命名风格:

capitalized = [name    capitalizedString];

rate        = [number  floatValue];

newString   = [string  decomposedStringWithCanonicalMapping];

subarray    = [array   subarrayWithRange:segment];

方法签名尽量做到含义明确。

不良的风格:

-sortInfo  // 是返回排序结果还是给info做排序

-refreshTimer  // 返回一个用于刷新的定时器还是刷新定时器

-update  // 更新什么,如何更新

良好的风格:

-currentSortInfo      // "current" 清楚地修饰了名词SortInfo

-refreshDefaultTimer  // refresh是一个动词。

-updateMenuItemTitle  // 一个正在发生的动作

方法类型修饰符+/-后要放置一个空格,各参数名之间也要放置一个空格。

良好的风格:

- (void)setExampleText:(NSString *)text image:(UIImage *)image;

如果方法的命名特别长,将方法名拆分成多行。

良好的风格:

color = [NSColor colorWithCalibratedHue: 0.10

                               saturation: 0.82

                              brightness: 0.89

                                    alpha: 1.00];

不要将私有的实例变量和方法声明在头文件中,应将私有变量和方法声明在实现文件的类扩展内。

不良的风格:

//MyViewController.h文件

@interface MyViewController : UIViewController<

 UITalbeViewDataSource,

 UITableViewDelegate> {

 @private:

  UITableView *_myTableView;  // 私有实例变量

}

// 内部使用的属性

@property (nonatomic,strong) NSNumber *variableUsedInternally;

- (void)sortName;  // 只用于内部使用的方法

@end

良好的风格:

//MyViewController.m文件使用类扩展

@interface MyViewController()<

 UITalbeViewDataSource,

 UITableViewDelegate> {

  UITableView *_myTableView;

// 外部需要访问的实例变量声明为属性,不需要外部访问的声明为实例变量

  NSNumber * variableUsedInternally;

}

// Xcode4.3开始,可以不写方法的前置声明,Interface BuilderStoryboard仍然可以找到方法的定义

@end

构造函数通常应该返回实例类型而不是id类型

参数

方法参数名前一般使用的前缀包括“the”、“an”、“new”。

良好的风格:

- (void)       setTitle:           (NSString *)   aTitle;

- (void)       setName:            (NSString *)   newName;

- (id)         keyForOption:       (CDCOption *)  anOption

- (NSArray *)  emailsForMailbox:   (CDCMailbox *) theMailbox;

- (CDCEmail *) emailForRecipients: (NSArray *)    theRecipients;

变量

变量的命令应尽量做到自描述。除了在for()循环语句中,单字母的变量应该避免使用(如i,j,k等)。一般循环语句的当前对象的命名前缀包括“one”、“a/an”。对于简单的单个对象使用“item”命名。

良好的风格:

for (i = 0; i < count; i++) {

    oneObject = [allObjects objectAtIndex: i];

    NSLog (@"oneObject: %@", oneObject);

}

      

NSEnumerator *e = [allObjects objectEnumerator];

id item;

while (item = [e nextObject])

      NSLog (@"item: %@", item);

指针变量的星号指示符应该紧靠变量,比如NSString *text,而不是NSString* textNSString * text

尽量的使用属性而非实例变量。除了在初始化方法(initinitWithCoder:等)、dealloc方法以及自定义settergetter方法中访问属性合成的实例变量,其他的情况使用属性进行访问。

良好的风格:

@interface RNCSection: NSObject

@property (nonatomic) NSString *headline;

@end

不良的风格:

@interface RNCSection : NSObject {

    NSString *headline;

}

当你使用@synthesize指令时,编译器会自动为你创建一个下划线_开头的的实例变量,所以不需要同时声明实例变量和属性。

不良的风格:

@interface RNCSection : NSObject {

    NSString *headline;

}

@property (nonatomic) NSString *headline;

@end

良好的风格:

@interface RNCSection: NSObject

@property (nonatomic) NSString *headline;

@end

不要使用@synthesize除非是编译器需要。注意在@protoco协议中的@optiona


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap