- 最好是既清晰又简短,但不要为简短而丧失清晰性
insertObject: atIndex:notinsert: at:(不清晰:要插入什么?“at”表示什么?) - 名称通常不缩写(禁止拼音!!!)
- 类名采用大驼峰(UpperCamelCase)
ps:订单来了项目有DD前缀,eg:DDUserModel - 类成员、方法小驼峰(lowerCamelCase)
- 局部变量大小写首选小驼峰,也可使用小写下划线的形式(snake_case)
- 以
alloc、copy、init、mutableCopy、new开头的方法要注意,它们会改变ARC的行为,不能作为方法前缀 - 以
get、set开头的方法有特殊的意义,不要随意定义。- set 是属性默认的设置方法,如果函数不是为了设置类成员,则不要用
set开头,可用setup替代。 - get 和属性方法无关,但在 Cocoa 中,其标准行为是通过引用传值,而不是直接返回结果的。欲获取变量,直接以变量名为名,如:
userInfomation,而不是getUserInfomation。
- set 是属性默认的设置方法,如果函数不是为了设置类成员,则不要用
例:
// OK
- (NSString *)name;
// 糟糕,应用上面的写法
- (NSString *)getName;
// OK,但极少使用
- (void)getName:(NSString **)buffer range:(NSRange)inRange;
// OK
- (NSSize)cellSize;
// 糟糕,应用上面的写法
- (NSSize)calcCellSize;
// 对 controller 做一般设置,OK
- (void)setupController;
// 列出具体设置的内容,更好
- (void)setupControllerObservers;
// 糟糕,set 专用于设置属性
- (void)setController;// 来自官方文档
insertObject:atIndex: // OK
insert:at: // 不清晰,插入了什么?at 具体指哪里?
removeObjectAtIndex: // OK
removeObject: // OK
remove: // 糟糕,什么被移除了?Objective-C 允许通过函数(C 形式的函数)描述行为,就如成员方法一样。如果隐含的类为单例或在处理函数子系统时,你应当优先使用函数,而不是类方法。 函数命名应该遵循如下几条规则:
-
函数命名与方法命名相似,但有两点不同:
1、它们有前缀,其前缀与你使用的类和常量的前缀相同
2、大写前缀后紧跟的第一个单词首字符
-
大多数函数名称以动词开头,这个动词描述该函数的行为
NSHighlightRect
NSDeallocateObject
属性声明的命名大体上和访问方法的命名是一致的。假如属性是动词或名词。例如:
@property (strong) NSString *title;
@property (assign) BOOL showsAlpha;
如果属性是形容词,名字去掉"is"前缀,但是要特别说明一下符合规范的get访问方法,例如
@property (assign, getter=isEditable) BOOL editable;
常量命名规则根据常量创建的方式不同而大不同。
- 使用枚举来定义一组相关的整数常量
- 枚举常量与其 typedef 命名遵守函数命名规则
typedef NS_ENUM(NSInteger, WalletCampType) {
WalletCampTypeNone = 0,
WalletCampTypeCreate,
WalletCampTypeAdd,
WalletCampTypeBoth
};
- 位掩码常量可以使用不具名枚举
typedef NS_OPTIONS(NSUInteger, YYTextDirection) {
YYTextDirectionNone = 0,
YYTextDirectionTop = 1 << 0,
YYTextDirectionRight = 1 << 1,
YYTextDirectionBottom = 1 << 2,
YYTextDirectionLeft = 1 << 3,
};
- 尽量用const来修饰浮点数常数,以及彼此没有关联的整数常量(否则使用枚举)
- const常量命名范例:
const float NSLightGray;
- 通常不使用 #define 来创建常量。如上面所述,整数常量请使用枚举,浮点数常量请使用const
- 使用大写字母来定义预处理编译宏。如:
#ifdef DEBUG
如果一个类有委托,那它的大部分通知可能由其委托的委托方法来处理。这些通知的名称应该能够反应其 响应的委托方法。订单来了项目中消息基本命名格式是:[DD] + Notification + [UniquePartOfName],例:
DDNotificationPermissionSettings好的协议名应能立刻让人分辨出这不是一个类名,除了以常用的 delegate、dateSource 做结尾外,还可以使用 …ing 这种形式,如:NSCoding、NSCopying、NSLocking。
好的命名规则可以不看代码就知道具体是做什么的。所以一个良好的命名规则是很重要的。结合订单来了,举一些例子:
ViewController: DDLoginViewController ([DD] + [UniquePartOfName] + ViewController)
Model: DDUserModel ([DD] + [UniquePartOfName] + Model)
View: DDShareView ([DD] + [UniquePartOfName] + View)
Logic: DDLoginApi ([DD] + [UniquePartOfName] + Api)
...
总之。最重要的一点就是清晰易懂,让人看文件命名就知道是做什么的。
-
方法注释
1、采用javadoc的格式,可以使用XCode插件VVDocumenter-Xcode快速添加,只需输入
///即可/** * 功能描述 * * @param tableView 参数说明 * @param section 参数说明 * * @return 返回值说明 */ - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [self.familyNames objectAtIndex:section]; }
2、
//注释// -tableView:shouldHighlightRowAtIndexPath: is called when a touch comes down on a row. // Returning NO to that message halts the selection process and does not cause the currently selected row to lose its selected look while the touch is down. - (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); - (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); - (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); -
TODO注释 注释确实是为了标记一些未完成的或完成的不尽如人意的地方, 这样一搜索, 就知道还有哪些活要干, 日志都省了。 格式://TODO:说明
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//TODO:增加初始化
return YES;
}-
用
#pragma mark -将函数或方法按功能进行分组。 -
dealloc方法放到实现文件的最顶部这样是为了时刻提醒你要记得释放相关资源。
-
delgate或协议相关方法放到一般内容之后。@property (...,...) #pragma mark - life cycle - (void)dealloc {} - (instancetype)init {} - (void)viewDidLoad {} - (void)viewWillAppear:(BOOL)animated {} - (void)didReceiveMemoryWarning {} #pragma mark - delegate #pragma mark - event response #pragma mark - private methods (说严格不应该写在这里,可以写成category或者模块) #pragma mark - getters and setters
主要描述开发过程中一些比较固定的实践技巧,写代码时可以直接套用
- 初始化方法的返回类型用
instancetype,不要用id
每当创建 NSString, NSDictionary, NSArray,和 NSNumber 类的不可变实例时,都应该使用字面量。要注意 nil 值不能传给 NSArray 和 NSDictionary 字面量,这样做会导致崩溃。
推荐:
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone" : @"Kate", @"iPad" : @"Kamal", @"Mobile Web" : @"Bill"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingZIPCode = @10018;
-
Objective-C的布尔值只使用
YES和NO -
true和false只能用于CoreFoundation,C或C++的代码中 -
禁止将某个值或表达式的结果与
YES进行比较因为BOOL被定义成signed char。这意味着除了YES(1)和NO(0)以外,它还可能是其他值。 因此C或C++中的非0为真并不一定就是YES
-
在C或C++代码中,要注意NULL指针的检测。
向一个nil的Objective-C对象发送消息不会导致崩溃。但由于Objective-C运行时不会处理给NULL指针的情况,所以为了避免崩溃,需要自行处理对于C/C++的NULL指针的检测。
-
在方法实现中,如果有block参数,要注意检测block参数为nil的情况。
- (void)exitWithCompletion:(void(^)(void))completion {
// 错误。 如果外部调用此方法时completion传入nil,此处会发生EXC_BAD_ACCESS
completion();
// 正确。如果completion不存在则不调用。
if (completion) {
completion();
}
}
就拿某个ViewController来说,如果其包含的功能已经很多或者还要增加更多功能的时候,就需要考虑到ViewController瘦身的问题 (ps:如果本身业务逻辑很简单,没必要瘦身)
- 自定义View,开发Api接口和delegate
- 把UITableView或者UICollectionView的DataSource隔离,使用block进行回调
- 使用扩展来设置基本属性
- ...