iOS 代码规范格式 Objective-C(下)

简介: iOS 代码规范格式 Objective-C(下)

三、命名规范



在撰写纯粹的Objective-C代码时,推荐使用驼峰命名法。


  • 3.1、文件名


文件名应该反映其中包含的类实现的名称,按照项目中的约定且大小写相关。常见的扩展名如下:


后缀 扩展名
.h C/C++/Objective-C header file
.m Objective-C implementation file
.mm Objective-C++ implementation file
.cc Pure C++ implementation file
.c C implementation file

[强制] 实现Category的文件名需包含类名,如 NSString+Utils.h 或 NSTextView+Autocomplete.h。


  • 3.2、Objective-C++
    在一个源码文件中, Objective-C++ 遵循你实现的函数/方法的风格。为了最小化在混合开发Cocoa/Objective-C和C++时由命名风格造成的冲突,遵循正在实现方法的风格。如果正在实现的方法是在 @implementation 块中, 使用Objective-C的命名规范。如果正在实现的方法是在C++的class中,则采用C++的命名规范。
    示例:
    文件: cross_platform_header.h


class CrossPlatformAPI {
public:
    ...
    int DoSomethingPlatformSpecific();  // 每个平台的实现都不一样
private:
    int an_instance_var_;
};
  • 文件: mac_implementation.mm


#include "cross_platform_header.h"
// 典型的Objective-C class, 使用Objective-C命名规范。
@interface MyDelegate : NSObject {
   @private
       int _instanceVar;
       CrossPlatformAPI *_backEndObject;
}
- (void)respondToSomething:(id)something;
@end
@implementation MyDelegate
- (void)respondToSomething:(id)something {
    // 从Cocoa桥接到C++的后端
    _instanceVar = _backEndObject->DoSomethingPlatformSpecific();
    NSString *tempString = [NSString stringWithFormat:@"%d", _instanceVar];
    NSLog(@"%@", tempString);
}
@end
// C++ class平台相关的实现, 使用C++命名规范
int CrossPlatformAPI::DoSomethingPlatformSpecific() {
    NSString *temp_string = [NSString stringWithFormat:@"%d", an_instance_var_];
    NSLog(@"%@", temp_string);
    return [temp_string intValue];
}


  • 3.3、类名
    [强制] 类名(包括Category和Protocol名)以大写字母开始,通过大小写而不是下划线分隔。
    [建议] 在设计可跨越多个应用之间共享的代码时,推荐使用前缀,(例如,GTMSendMessage)。还有很多外部依赖库的大型应用中设计的类最好也使用前缀。
    [强制] 若使用前缀,则前缀缩写要大于2个字符


  • 3.4、Category名
    [强制] 类别(Category)名中需要加入被扩展的类名。比如:比如我们要给NSString类加一个解析的功能,我们创建一个category,命名为GTMStringParsingAdditions,并且放在名为NSString+Parsing.h的文件中。
    [强制] 类名与括号中间需要有一个空格。


示例
扩展一个framework类:


@interface NSString (GTMStringParsingAdditions)
- (NSString *)foobarString:
@end
//使方法和属性私有化
@interface FoobarViewController ()
@property(nonatomic, retain) NSView *dongleView;
- (void)performLayout;
@end
  • 3.5、Objective-C 方法名
    [强制] 方法名应该以小写字母开头,混合大小写。每个命名参数也应该以小写字母开头。
    [建议] 方法名称应该尽可能读起来像句子,意味着你应该选择能够搭配方法名的参数名。(比如:convertPoint:fromRect:或replaceCharactersInRange:withString:)。
    [建议] getter类型的方法不加get前缀。
    示例


- (id)getDelegate;  // 应避免的
- (id)delegate;    // 推荐的
  • [强制] 在所有参数前面添加关键字
    示例


// 推荐的
- (void)sendAction:(SEL)aSelector toObject:(id)anObject forAllCells:(BOOL)flag; 
// 错误的
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;
  • [建议] 确保参数前面的关键字可以正确描述参数
    示例


// 推荐的
- (id)viewWithTag:(NSInteger)aTag;
// 错误的
- (id)taggedView:(int)aTag;
  • [强制] 当需要基于已有的一个方法创建新方法时,请将新的关键字添加到原有方法后面


示例


// 原有方法
- (id)initWithFrame:(CGRect)frameRect; 
// 新方法
- (id)initWithFrame:(NSRect)frameRect mode:(int)aMode cellClass:(Class)factoryId numberOfRows:(int)rowsHigh numberOfColumns:(int)colsWide;
  • [建议] 尽量不要使用 and  描述参数
    示例


// 推荐的
- (int)runModalForDirectory:(NSString *)path file:(NSString *) name types:(NSArray *)fileTypes;        
//错误的
- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;
  • 这些规定适用于Objective-C的方法。C++方法名称和函数仍沿用C++风格要求。


  • 3.6、变量名[强制] 变量名以小写字母开头,混合大小写以区分单词。
  • 3.6.1、普通变量名
    [建议] 不要使用匈牙利命名法,比如不要使用变量的静态类型(int 或 pointer)。尽量写具有描述意义的名称。
    比如不要使用下面的变量命名,示例


int w;
int nerr;
int nCompConns;
tix = [[NSMutableArray alloc] init];
obj = [someObject object];
p = [network port];
  • 建议使用如下的变量命名:


int numErrors;
int numCompletedConnections;
tickets = [[NSMutableArray alloc] init];
userInfo = [someObject object];
port = [network port];
  • 3.6.2. 类成员变量
    [建议] 类成员变量的命名是在普通变量的名字前,添加一个下划线做前缀,比如 _usernameTextField
  • 3.6.3. 常量
    [建议] 常量名(宏,本地常变量等)首字母应该以小写的k开头,然后使用混合大小写区分单词,枚举值前面需要以枚举名为前缀。例如:


const int kNumberOfFiles = 12;
NSString *const kUserKey = @"kUserKey";
enum DisPlayTinge {
    DisplayTingeGreen = 1
    DisplayTingeBlue = 2
};
  • 总结:变量名应该以小写字母开头,并混合大小写。类的成员变量应该以m_作为前缀。例如:myLocalVariable、m_myInstanceVariable。如果不能使用Objective-C 2.0的@property,使用KVO或者KVC绑定的成员变量可以以一个下划线作为前缀。


四、注释



  • 4.1、文件注释
    [建议] 创建文件时会生成默认的注释。如果看了文件名还不懂该文件是干什么,可以有选择的在一个文件开头写一段关于内容的描述。
  • 4.2、声明部分的注释
    [建议] 每个接口,类别,协议的声明都应该有个伴随的注释,来描述它的作用以及它如何融入整体环境。注释遵循apple doc风格,以///开始,///结束。
    [强制] 声明部分的注释如果以“//”开头,且与代码同一行,在 “//” 前加空格。


示例


/// <#Description#>
/// @param nibNameOrNil <#nibNameOrNil description#>
/// @param nibBundleOrNil <#nibBundleOrNil description#>
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
@property (copy) NSString *host; // network host
  • [建议] 公共接口的每个方法,都应该有注释来解释它的作用、参数、返回值以及其它影响。
  • 4.3、实现部分的注释
    [强制] 实现部分的注释如果以“//”开头,且与代码同一行,在 “//“ 前加空格。


五、Cocoa 和 Objective-C 特性



  • 5.1、重载指定构造函数
    [强制] 当写子类的时候,如果需要init...方法,必须重载父类的指定构造函数。
  • 5.2、重载 NSObject 的方法
    [建议] 如果重载了NSObject类的方法,建议把它们放在@implementation内的前边,这也是惯例。 通常适用(但不局限)于 init...,copyWithZone:,以及dealloc方法。所有init...应放在一起,后面跟着其他NSObject的方法。
  • 5.3、初始化
    [建议] 不要在 init 方法中,将成员变量初始化为 0或 nil。如果一个对象可被复用,状态需要全部重置,这时可引入 reset方法。
    [强制] 局部变量不会被编译器初始化,所有局部变量使用前必须初始化。
  • 5.4、避免调用+ new
    [强制] 不要调用NSObject的类方法new,也不要在子类中重载它。使用alloc和init方法创建并初始化对象。
  • 5.5、保持公共 API 简单[建议] 保持公共API简单,避免“包含一切式“的API。示例


// GTMFoo.m
#import "GTMFoo.h"
@interface GTMFoo (PrivateDelegateHandling)
- (NSString *)doSomethingWithDelegate;  // Declare private method
@end
@implementation GTMFoo(PrivateDelegateHandling)
...
- (NSString *)doSomethingWithDelegate {
    // Implement this method
}
...
@end
  • 解释:可以使用私有Category保证公共头文件整洁示例


@interface GTMFoo () { ... }
  • 5.6、#import 与 #include
    [强制] 使用#import来引用 Objective-C/Objective-C++ 头文件,使用#include引用C/C++头文件。
  • 5.7、使用根框架
    [强制] 包含根框架,而非单独的文件。
    示例


#import <Foundation/Foundation.h> // 推荐
#import <Foundation/NSArray.h> // 避免
#import <Foundation/NSString.h> // 避免
...
  • 5.8、在init和dealloc中避免使用存取方法
    [建议] 在init和dealloc方法执行的过程中,子类可能会处在一个不稳定状态,所以这些方法中应避免调用存取方法,应在这些方法中直接对成员变量进行赋值或释放操作。
    示例


- (instancetype)init {
     self = [super init];
     if (self) {
        _bar = [[NSMutableString alloc] init];  // 推荐
     }
     return self;
}
- (void)dealloc {
    [_bar release];                           // 推荐
    [super dealloc];
}
- (instancetype)init {
    self = [super init];
    if (self) {
       self.bar = [NSMutableString string];  // 避免
    }
    return self;
}
- (void)dealloc {
    self.bar = nil;                         // 避免
    [super dealloc];
}
  • 5.9、按照声明顺序销毁实例变量
    [建议] dealloc中对象被释放的顺序应该与他们在 @interface 中声明的顺序一致,这有助于代码检查。


  • 5.10、setter中对NSString进行copy
    [建议] 接受NSString作为参数的setter,应该copy它所接受的字符串。
    示例


- (void)setFoo:(NSString *)aFoo {
   [_foo autorelease];
   _foo = [aFoo copy];
}
  • 5.11、避免抛出异常
    [建议] 不要 @throw Objective-C 异常,但要注意从第三方的调用或者系统调用捕捉异常。如果确实使用了异常,请注释期望什么方法抛出异常。


  • 5.12、BOOL的使用
    Objective-C 中定义BOOL为无符号字符型,这就意味着BOOL类型可以有不同于 YES(1) 或者 NO(0)的值。不要直接把整形转换成 BOOL。常见的错误包括将数组的大小、指针值以及位运算的结果直接转换成BOOL,这取决于整型结果的最后一个字节,可能产生一个NO的值。当转换整型至 BOOL 时,使用三目操作符来返回 YES或者NO。
    [强制] 不要直接将 BOOL 值与 YES 、NO进行比较。
    [建议] 对 BOOL 使用逻辑运算符(&&, || 和 !)是合法的,返回值也可以安全地转换成 BOOL。
    示例


- (BOOL)isBold {
    return [self fontTraits] & NSFontBoldTrait;
}
- (BOOL)isValid {
    return [self stringValue];
}
- (BOOL)isBold {
    return ([self fontTraits] & NSFontBoldTrait) ? YES : NO;
}
- (BOOL)isValid {
    return [self stringValue] != nil;
}
- (BOOL)isEnabled {
    return [self isValid] && [self isBold];
}
  • 解释,同样,不要直接比较 YES/NO 和 BOOL 变量。不仅仅影响可读性,结果可能与你想的不同


示例


错误的写法


BOOL great = [foo isGreat];
if (great == YES) {
     // ...
}
  • 正确的写法


BOOL great = [foo isGreat];
if (great) {
     // ...be great!
}
  • 5.13、属性
  • 5.13.1、命名
    [建议] 属性所关联的实例变量的命名必须遵守以下划线作为前缀的规则。属性的名字应该与成员变量去掉下划线后缀的名字一模一样。@property后面紧跟括号,不留空格。


示例


@interface MyClass : NSObject
@property(copy, nonatomic) NSString *name;
@end
@implementation MyClass
// No code required for auto-synthesis, else use:
// @synthesize name = _name;
@end
  • 5.13.2、位置
    [强制] 属性的声明必须紧靠着类接口中的实例变量语句块。属性的定义必须在 @implementation 的类定义的最上方。他们的缩进与包含他们的 @interface 以及 @implementation 语句一样。


示例


@interface MyClass : NSObject {
    @private
       NSString *_name;
}
@property(copy, nonatomic) NSString *name;
@end
@implementation MyClass
@synthesize name = _name;
- (instancetype)init {
    ...
}
@end
  • 5.13.3、字符串应使用 copy 属性
    [强制] 应总是用 copy 属性声明 NSString 属性。这从逻辑上遵守了 NSString的setter必须使用copy而不是 retain。


  • 5.14、没有实例变量的接口
    [强制] 没有声明任何实例变量的接口,应省略空大括号。
    示例


@interface MyClass : NSObject
// Does a lot of stuff
- (void)fooBarBam;
@end
@interface MyClass : NSObject {
}
// Does a lot of stuff
- (void)fooBarBam;
@end
  • 5.15、自动synthesize实例变量
    [建议] 优先考虑使用自动 synthesize 实例变量。
    示例


// Header file
@protocol Thingy
@property(nonatomic, copy) NSString *widgetName;
@end
@interface Foo : NSObject<Thingy>
// A guy walks into a bar.
@property(nonatomic, copy) NSString *bar;
@end
// Implementation file
@interface Foo ()
@property(nonatomic, retain) NSArray *baz;
@end
@implementation Foo
@synthesize widgetName = _widgetName;
@end


目录
相关文章
|
1月前
|
安全 编译器 Swift
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
135 2
|
28天前
|
存储 Android开发 iOS开发
iOS不支持HEIC格式的图片显示和标签函数显示问题及解决方案
iOS不支持HEIC格式的图片显示和标签函数显示问题及解决方案
32 0
|
25天前
|
存储 Web App开发 Android开发
iOS不支持WebP格式图片解决方案和iPhone 7及其后硬件拍照的HEIC格式图片
iOS不支持WebP格式图片解决方案和iPhone 7及其后硬件拍照的HEIC格式图片
38 1
iOS不支持WebP格式图片解决方案和iPhone 7及其后硬件拍照的HEIC格式图片
|
1月前
|
缓存 开发工具 iOS开发
优化iOS中Objective-C代码调起支付流程的速度
优化iOS中Objective-C代码调起支付流程的速度
22 2
|
1月前
|
安全 JavaScript 前端开发
IOS开发基础知识:介绍一下 Swift 和 Objective-C,它们之间有什么区别?
IOS开发基础知识:介绍一下 Swift 和 Objective-C,它们之间有什么区别?
97 0
|
JSON 数据格式 iOS开发
iOS基础 JSON格式
iOS基础 JSON格式
110 0
|
JSON 移动开发 数据格式
iOS url传递JSON格式参数方法
iOS url传递JSON格式参数方法
230 0
|
移动开发 开发工具 iOS开发
ios打包如何生成p12格式的证书和证书profile文件
做过H5多端开发ios app的同学们,肯定知道,打包ios应用,需要一个.p12后缀的ios打包证书和一个证书profile文件。 苹果官方提供的方法,生成这个证书需要苹果开发者账号和mac苹果电脑,但是我们大多数uniapp的开发者,都是使用windows电脑进行开发的,没有mac电脑,那么如何在windows电脑上生成ios证书呢?
1367 0
ios打包如何生成p12格式的证书和证书profile文件
|
iOS开发 容器
iOS 代码规范格式 Objective-C(上)
iOS 代码规范格式 Objective-C
388 0
iOS 代码规范格式 Objective-C(上)