| 版本 | 內(nèi)容 | 修訂人 | 時(shí)間 |
|---|---|---|---|
| 0.1.0 | 草稿 | 黃鑫 | 2018/06/11 |
| 0.2.0 | 修改文檔組織 | 黃鑫 | 2018/06/16 |
0. 前言
"代碼是寫給人看的"
例子??
//
// M2User.h
// M2API
//
// Created by Kim on 2018/06/11.
//
// 頭文件引入
#import <Foundation.h>
#import "M2Defines.h"
// 常量定義
FOUNDATION_EXPORT NSString * const M2UserErrorDomain;
/**
性別枚舉
*/
typedef NS_ENUM(NSUInteger, M2Gender) {
M2GenderUnknow = 0, //!< 未知
M2GenderMale, //!< 男性
M2GenderFemale //!< 女性
};
/** 用戶 */
@interface M2User : NSObject
@property (nonatomic, readonly, copy) NSString *name; //!< 名字
@property (nonatomic, readonly, assign) NSUInteger age; //!< 年齡
@property (nonatomic, readonly, assign) M2Gender gender; //!< 性別
/**
初始化
@param name 用戶名
@param age 年齡
@param gender 性別
*/
+ (instancetype)userWithName:(NSString * __Nonnull)name
age:(NSUInteger)age
gender:(M2Gender)gender;
- (instancetype)initWithName:(NSString * __Nonnull)name
age:(NSUInteger)age
gender:(M2Gender)gender;
@end
// 實(shí)現(xiàn)
@implementation M2User
+ (instancetype)userWithName:(NSString * __Nonnull)name
age:(NSUInteger)age
gender:(M2Gender)gender {
return [[self alloc] initWithName:name age:age gender:gender];
}
- (instancetype)initWithName:(NSString * __Nonnull)name
age:(NSUInteger)age
gender:(M2Gender)gender {
if (self = [super init]) {
_name = name;
_age = age;
_gender = gender;
}
return self;
}
@end
1. 布局與風(fēng)格
良好布局的目的
- 準(zhǔn)確表現(xiàn)代碼的邏輯結(jié)構(gòu)
- 始終如一地表現(xiàn)代碼的邏輯結(jié)構(gòu)
- 改善可讀性
- 經(jīng)得起修改
布局技術(shù)
- 分組 從另一個(gè)角度看,空白也是分組,也是確保相關(guān)到語(yǔ)句組成放在一起。
- 空行 是指示一個(gè)程序如何組織的手段。可以用空行將相關(guān)語(yǔ)句各自劃分成段落,分開各個(gè)子程序,突出注釋部分。
- 縮進(jìn) 使用縮進(jìn)形式顯示程序的邏輯結(jié)構(gòu)。
“當(dāng)程序有兩到四個(gè)空格的縮進(jìn)時(shí),受試者對(duì)程序的理解分?jǐn)?shù)會(huì)比毫無縮進(jìn)的程序高出20%到30%?!?/p>
— 《程序縮進(jìn)和可理解性》
2. 代碼組織
Objective-C的類通常分成頭文件和實(shí)現(xiàn)文件。
頭文件
頭文件通常包含:
- 文件說明與版權(quán)
- 頭文件引入
- 宏定義
- 常量定義
- 類型前置聲明
- 塊類型定義
- 枚舉定義
- 函數(shù)定義
- 協(xié)議定義
- 類定義 - 類定義通常包含
- 類方法。
- 屬性。
- 公開方法。
- 分類定義
- 分類方法。
?? 注意:內(nèi)容排列順序與上面一致。
如下面的頭文件模板所示。按照下面的順序定義。
// 文件說明與版權(quán)
//
// M2API2Client.h
// M2API
//
// Created by Kim on 2017/11/11.
// Copyright (c) 2017 Kim Studio. All rights reserved.
//
// 頭文件引入 (見下文說明)
#import <Foundation.h>
#import "M2APIClient.h"
// 宏定義 (見下文說明。必須是才使用宏)
#define M2_DEBUG 0
#define M2_TEST 1
// 常量定義
FOUNDATION_EXPORT NSString * const M2UserErrorDomain;
// 類型前置聲明
@class User;
// 類型定義
typedef NSString * const M2APIHTTPMethod;
// Block類型定義
typedef void (^M2APISuccessBlock)(id response);
typedef void (^M2APIFailureBlock)(NSError *error);
// 枚舉定義
typedef NS_ENUM(NSUInteger, M2DirectionType) {
M2DirectionTypeUnknown = 0,
M2DirectionTypeTop,
M2DirectionTypeLeft,
M2DirectionTypeButtom,
M2DirectionTypeRight
};
// 協(xié)議定義
@protocol M2LoginViewDelegate : NSObject
@end
// 類定義
@interface M2User : NSObject
@property (nonatomic, readonly, copy) NSString *name;
@end
// 分類定義
@interface M2User <M2Debug>
- (NSString *)debugInfo;
@end
?? 通常使用文件模板
版權(quán)
文件頭中增加版權(quán)信息。
//
// M2API2Client.h
// M2API
//
// Created by Kim on 2017/11/11.
// Copyright (c) 2017 Kim Studio. All rights reserved.
//
頭文件引入
頭文件引入規(guī)則順序:
- 系統(tǒng)庫(kù)
- 第三方庫(kù)
- 工程內(nèi)類引入
注意:
- 系統(tǒng)庫(kù)/第三方庫(kù)與工程內(nèi)類引入直接的分組空行。
- 工程內(nèi)類如果有多個(gè)頭文件引入,也可以增加空行按功能進(jìn)行分組。
//
// M2API2Client.h
// M2API
//
// Created by Kim on 2017/11/11.
// Copyright (c) 2017 Kim Studio. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AFNetworking/AFNetworking.h>
#import <CocoaLumberjack/CocoaLumberjack.h>
#import <AFHTTPSessionManagerLogger.h>
#import "M2APIConfiguration.h"
#import "M2APIHTTPSessionManager.h"
實(shí)現(xiàn)文件
實(shí)現(xiàn)文件通常包含:
// 文件描述
// 頭文件引入
// 常量定義
// 文件內(nèi)私有類定義
// 類私有方法定義
// 類實(shí)現(xiàn)
類定義
一般類定義組成如下:
- 協(xié)議
- 類
- 成員變量
- 屬性
- 類方法
- 構(gòu)造函數(shù)
- 公開方法
- 控件響應(yīng)函數(shù)
- 通知響應(yīng)函數(shù)
- 委托方法
- 私有方法
空行與注釋:
- 協(xié)議與類之間留2行空行。
-
@protocol/@interface與第一個(gè)屬性或方法后,空1行。 - 最后一個(gè)方法與
@end之間空1行。 - 類最后空1行。
- 屬性與第一個(gè)方法之間空1行。
- 屬性如果有長(zhǎng)注釋,則空1行。
-
屬性如果使用短注釋,則在屬性后使用
//!<進(jìn)行注釋。 - 如果方法定義有注釋,則空1行。
- 如果方法定義沒有注釋,則可以不留空行進(jìn)行分組。
- 方法分組之間,空1行。
- 函數(shù)定義的注意點(diǎn),見后面函數(shù)一節(jié)
////// 頭文件說明
//
// M2APIUserClient.h
// M2UserAPI
// Created by Kim on 2018/06/10
// Copyright (c) 2017 Kim Studio. All rights reserved.
////// 頭文件引入
#import <M2HTTPClient.h>
#import "M2APIUser.h"
////// 協(xié)議定義
@protocol M2APIUserEndPoint <NSObject>
/**
登陸
@param user 用戶名
@param password 密碼
@return 信號(hào) M2APIUser
*/
- (RACSignal *)loginWithUser:(NSString *)user password:(NSString *)password;
/**
獲取用戶信息
@return 信號(hào) 用戶信息
*/
- (RACSignal *)userInfo;
@end
/////// 類定義
/**
用戶模塊客戶端
*/
@interface M2APIUserClient : M2HTTPClient <M2APIUserEndPoint>
@property (nonatomic, strong) M2APIConfiguration *configuration; //!< 配置消息
@property (nonatomic, strong) M2APISigner *signer; //!< 簽名類
+ (instancetype)sharedClient;
+ (instancetype)clientWithConfiguration:(M2APIConfiguration *)configuration;
- (instancetype)initWithConfiguration:(M2APIConfiguration *)configuration;
@end
類實(shí)現(xiàn)
類實(shí)現(xiàn)內(nèi)部組織 使用#pargma mark -來分割功能組。一個(gè)典型的ViewController的實(shí)現(xiàn)功能分組有:
-
類方法。
- 單件函數(shù)。
- 其他類方法。
-
Lifecycle。 對(duì)象生命周期函數(shù)
- 對(duì)象生命周期函數(shù)。
init,dealloc,descrition。
- 對(duì)象生命周期函數(shù)。
自定義屬性。
UI對(duì)象的事件響應(yīng)函數(shù)。
公開方法。
私有方法和輔助函數(shù)。
通知處理函數(shù)。
委托方法。
#pargma mark - Class methods
+ (instancetype)sharedInstance {}
+ (CGFloat)viewHeightForObject:(id)object {}
#pargma mark - Lifecycle
- (instancetype)init {}
- (void)dealloc {}
- (void)viewDidLoad {}
- (void)viewWillAppear:(BOOL)animated {}
- (void)didReceiveMemoryWarning {}
#pargma mark - Custom Accessors
- (void)setCustomProperty:(id)value {}
- (id)customProperty {}
#pargma mark - IBActions
- (IBAction)onSubmitDataAction:(id)sender {}
#pargma mark - Public
- (void)publicMethod {}
#pargma mark - Private helpers or utils
- (void)m2_privateMethod {}
#pargma mark - Notification Handlers
- (void)onEnterBackgroundHandler:(NSNotification *)notification {}
#pargma mark - Delegate methods
// 多個(gè)delegate 進(jìn)行分組
?? 使用文件模板
3. 命名
Apple命名規(guī)則盡可能堅(jiān)持,特別是與這些相關(guān)的memory management rules(NARC)。
長(zhǎng)的,描述性的方法和變量命名是好的。
命名涉及到比較多:
- 庫(kù)名
- 文件名
- 類名
- 函數(shù)名
- 變量名
庫(kù)名
設(shè)計(jì)一個(gè)庫(kù)通常使用前綴+名稱的方式。eg.
- UIKit
- AVFoundation
- SDWebImage
- AFNetworking
文件名
文件名命名規(guī)則與類命名規(guī)則一致:
- 命名空間。本項(xiàng)目/或項(xiàng)目模塊縮略前綴。eg.
M2API,M2BL,M2PL。 - 功能名詞。User,Device,F(xiàn)ile,VideoPlayer。
- 功能分類名字。例如,
-
Client代表DAL的網(wǎng)絡(luò)訪問客戶端。 -
Data代表DAL的DTO (Data Transfer Object)。 - 使用名詞作為領(lǐng)域模型名稱。
-
Service代表BL的業(yè)務(wù)邏輯類。 -
Item代表PL中View的VO(View Object)。 -
View代表PL的視圖類。 -
Controller代表PL的中MVC模式的C控制器 -
ViewModel/Store代表PL的MVVM的VM或者M(jìn)VCS的S。
-
eg.
UIViewController.hM2PLLoginView.h
命名空間
由于Objective-C 沒有命名空間,所以通常使用項(xiàng)目名的頭字母用于:
宏
常量
枚舉
C函數(shù)名
全局變量名
類名
塊類型名
前綴應(yīng)由不少于3個(gè)字母組成(蘋果保留所有2個(gè)字母的前綴)。可以是APP名、公司名縮寫等。
例子??
// 宏
#debug M2_DEBUG
// 常量
FOUNDATION_EXPORT NSString * const M2UserErrorDomain;
// 別名
typedef NSString * const M2HTTPMethod;
// 塊類型名
typedef void (^M2APISuccessBlock)(id response);
typedef void (^M2APIFailureBlock)(NSError *error);
// 類名
@class M2User;
宏
盡量少使用宏來定義常量。宏通常用于編譯條件。
- 增加命名空間。
- 單詞使用大寫。
- 使用下劃線連接單詞。
使用
#define M2_DEBUG
不使用
#define Production
#define M2_Production
常量
常量通常使用與字符串類型常量與值類型常量。注意點(diǎn):
- 命名空間。命名空間前綴全部大寫
- 使用駝峰命名
// 頭文件 .h
FOUNDATION_EXPORT NSString * const M2UserErrorDomain;
FOUNDATION const CGFloat M2UserMaxAge;
// 實(shí)現(xiàn)文件 .m
static NSString * const M2UserError = @"net.kim.M2UserErrorDomain"; // 跨文件使用
static const CGFloat M2UserMaxAge = 200; // 跨文件使用
static const CGFloat M2UserMinAge = 0; // 文件內(nèi)部使用
塊類型
塊類型定義。注意點(diǎn):
- 命名。命名空間 + 功能名詞 +
Block。- 命名空間。見《命名空間一節(jié)》
- 功能名詞。
- 后綴
Block。以區(qū)別其他類型。
- 注意返回類型后需要增加一個(gè)空格。
例
typedef void (^M2APISuccessBlock)(id response);
typedef void (^M2APIFailureBlock)(NSError *error);
4. 類
- 類方法
- 單例模式
- 屬性
- 實(shí)例方法
類方法
單例模式
單例對(duì)象應(yīng)該使用線程安全模式來創(chuàng)建共享實(shí)例。
+ (instancetype)sharedInstance {
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
這會(huì)防止possible and sometimes prolific crashes.
屬性
公開屬性
屬性特性排列順序如下:
- 是否原子
atomic/nonatomic。雖然默認(rèn)為atomic, 原子訪問時(shí)還是需要顯式說明。 - 讀寫
readonly/readwrite。默認(rèn)為readwrite。只讀是需要顯式說明。 - 訪問器
getter/setter。如果是布爾類型getter,需要加is前綴。 - 存儲(chǔ)特性
weak/strong/copy/assign。放在最后。
??Tip 不可變性
Immutable為了避免數(shù)據(jù)遭到不必要的修改:
- 不應(yīng)該被外部直接修改的屬性,應(yīng)該聲明
(readonly)(可以在Extension中重新聲明為(readwrite),使它對(duì)外只讀,對(duì)內(nèi)可讀寫)。- 不要把
NSMutable(Array/Dictionary/Set...)暴露出來,應(yīng)該只留一個(gè)setter給外部使用,以免它們被其他類修改時(shí),類自身難以察覺。- 如果數(shù)據(jù)不是特別多,
copy的代價(jià)不是特別大,留給其他類的getter應(yīng)盡量用copy方法,返回一個(gè)不可變的對(duì)象。
例子
@property (nonatomic, readonly, copy) NSString *name;
@property (nonatomic, readonly, assign) NSUInteger age;
@property (nonatomic, readonly, assign) M2Gender gender;
@property (nonatomic, readonly, getter=isLogin, assign) BOOL login;
??Tip 控件屬性命名
- 控件功能名詞 + 后綴不帶命名空間的控件類型名
例子
@interface M2PLoginView : UIView
@property (nonatomic, weak) IBOutlet UILabel *userLabel; //!< 用戶名標(biāo)簽
@property (nonatomic, weak) IBOutlet UITextField *userTextField; //!< 用戶名輸入
@end
私有屬性
如果私有屬性在模塊內(nèi)部可以訪問,則使用私有頭文件。
eg. M2User_Private.h 在有需要使用到的實(shí)現(xiàn)文件引入即可。
?? 注意:私有頭文件,在模塊外部不可訪問。生成庫(kù)時(shí)需要注意忽略改頭文件。
例子
/// 實(shí)現(xiàn)文件
@interface M2User ()
@property (nonatomic, copy)NSString *name;
@property (nonatomic, assign)NSUInteger age;
@property (nonatomic, assign)M2Gender gender;
@end
@implementation M2User
// ...
@end
自定義屬性
下面是一個(gè)懶加載的自定義屬性:
- (NSMultableDictionary *)extraInfo {
if (!_extraInfo) {
_extraInfo = [NSMutableDictionary dictionary];
}
return _extraInfo
}
自定義屬性設(shè)置:
- (void)setExtraInfo:(NSDictionary *)extraInfo {
_extraInfo = extraInfo;
// Do something else.
// 其他副作用。
}
?? 注意:在自定義屬性內(nèi)增加副作用需要特別注意。需要在屬性增加注釋說明。
成員變量
私有屬性,一般定義在類的實(shí)現(xiàn)文件。
/// 實(shí)現(xiàn)文件
@interface M2User () {
BOOL _status;
}
@end
@implementation M2User
// ...
@end
標(biāo)識(shí)位
@interface Fool () {
struct {
BOOL step1Done;
BOOL step2Done;
} _flags;
}
// 使用
_flag.step1Done = YES;
_flag.step1Done = NO;
類初始化方法
@interface Airplan
+ (instancetype)airplanWithType:(AirplanType)type;
@end
@implementation Airplan
關(guān)于更多instancetype信息,請(qǐng)查看NSHipster.com
Init方法
Init方法應(yīng)該遵循Apple生成代碼模板的命名規(guī)則。返回類型應(yīng)該使用instancetype而不是id
- (instancetype)init {
if (self = [super init]) {
// ...
}
return self;
}
// 或者
- (instancetype)initWithName:(NSString *)name {
self = [super init];
if (self) {
// ...
}
return self;
}
查看關(guān)于instancetype的文章Class Constructor Methods
方法定義
響應(yīng)函數(shù)
規(guī)則:
-
控件響應(yīng)函數(shù):前綴
on+ 功能動(dòng)作 + 后綴Action。 -
通知響應(yīng)函數(shù):前綴
on+ 通知 + 后綴Handler。
使用
// 控件響應(yīng)函數(shù)
- (IBAction)onLoginAction:(id)sender {
// ...
}
// 通知響應(yīng)函數(shù)
- (void)onEnterBackgroundHandler:(NSNotification *)notification {
// ...
}
不使用
- (IBAction)login:(id)sender {
// ...
}
- (void)enterBackground:(NSNotification *)noti {
// ...
}
分類
@interface M2APIUserClient (User)
// 登陸
- (RACSignal *)loginWithUser:(NSString *)user password:(NSString *)password;
// 登出
- (RACSignal *)logout;
@end
5. 子程序
變量[TODO]
布爾值
Objective-C使用YES和NO。因?yàn)?code>true和false應(yīng)該只在CoreFoundation,C或C++代碼使用。既然nil解析成NO,所以沒有必要在條件語(yǔ)句比較。不要拿某樣?xùn)|西直接與YES比較,因?yàn)?code>YES被定義為1和一個(gè)BOOL能被設(shè)置為8位。
這是為了在不同文件保持一致性和在視覺上更加簡(jiǎn)潔而考慮。
使用
if (someObject) {}
if (![anotherObject boolValue]) {}
不使用
if (someObject == nil) {}
if ([anotherObject boolValue] == NO) {}
if (isAwesome == YES) {} // Never do this.
if (isAwesome == true) {} // Never do this.
如果BOOL屬性的名字是一個(gè)形容詞,屬性就能忽略"is"前綴,但要指定get訪問器的慣用名稱。例如:
@property (assign, getter=isEditable) BOOL editable;
文字和例子從這里引用Cocoa Naming Guidelines
條件語(yǔ)句if/else
條件語(yǔ)句主體為了防止出錯(cuò)應(yīng)該使用大括號(hào)包圍,即使條件語(yǔ)句主體能夠不用大括號(hào)編寫(如,只用一行代碼)。這些錯(cuò)誤包括添加第二行代碼和期望它成為if語(yǔ)句;還有,even more dangerous defect可能發(fā)生在if語(yǔ)句里面一行代碼被注釋了,然后下一行代碼不知不覺地成為if語(yǔ)句的一部分。除此之外,這種風(fēng)格與其他條件語(yǔ)句的風(fēng)格保持一致,所以更加容易閱讀。
使用
// Good!
if (!error) {
return success;
}
不使用
// Bad
// 沒有花括號(hào),容易多些空行,造成邏輯提前返回。
if (!error)
return success;
if (!error) return success;
if (error != nil)
return success
多條件情而且單行過長(zhǎng)的情況下,使用換行。條件符放行最后。
使用
// Good!
if (direction == M2Left ||
direction == M2Right) {
// ...
}
不使用
// Bad!
if (direction == M2Left
|| direction == M2Right) {
// ...
}
使用
if (user.isHappy) {
// Do something
} else {
// Do something else
}
不使用
if (user.isHappy)
{
// ...
}
else {
// ...
}
Switch-Case
- (void)handleMessage:(M2Message *)message {
// 注意花括號(hào)與break。
M2MessageType type = message.type;
switch(type) {
case M2MessageChat: {
// ...
} break;
case M2MessageNotify: {
// ...
} break;
case M2MessageSystem: {
// ...
} break;
default:
break;
}
}
三元操作符 ?:
當(dāng)需要提高代碼的清晰性和簡(jiǎn)潔性時(shí),三元操作符?:才會(huì)使用。單個(gè)條件求值常常需要它。多個(gè)條件求值時(shí),如果使用if語(yǔ)句或重構(gòu)成實(shí)例變量時(shí),代碼會(huì)更加易讀。一般來說,最好使用三元操作符是在根據(jù)條件來賦值的情況下。
Non-boolean的變量與某東西比較,加上括號(hào)()會(huì)提高可讀性。如果被比較的變量是boolean類型,那么就不需要括號(hào)。
使用
NSInteger value = 5;
result = (value != 0) ? x : y;
Bool isHorizontal = YES;
result = isHorizontal ? x : y;
NSString *name = nil;
result = name ?: @"";
不使用
BOOL result = value!=0 ?x:y;
塊block
使用
typedef void (^M2SuccessBlock)(id response);
M2SuccessBlock successBlock = ^(id response) {
// Do something.
};
不使用
// 可讀性不夠強(qiáng),另外可能導(dǎo)致過長(zhǎng)行。
void (^successBlock)(id response) = ^(id response) {
// Do something.
};
使用
// 風(fēng)格1
[userClient loginWithUser:user password:password success:^(id user) {
// do something.
} failure:^(NSError *error) {
// ...
}];
// *******************************************
// 如果success/failure塊過長(zhǎng),則可以前綴定義塊。
// 風(fēng)格2
M2APISuccessBlock successBlock = ^(id response) {
// do something.
};
M2APIFailureBlock failureBlok = ^(NSError *error) {
// ...
};
// 單行過長(zhǎng),則換行。
[userClient loginWithUser:user
password:password
success:successBlock
failure:failureBlock];
字面值
使用
// 數(shù)組
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
// 字典
NSDictionary *productManagers = @{@"iPhone": @"Kate", @"iPad": @"Kamal", @"Mobile Web": @"Bill"};
// Number
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingStreetNumber = @10018;
不使用
// 數(shù)組
NSArray *names = [NSArray arrayWithObjects:@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul", nil];
// 字典
NSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @"Kate", @"iPhone", @"Kamal", @"iPad", @"Bill", @"Mobile Web", nil];
// Number
NSNumber *shouldUseLiterals = [NSNumber numberWithBool:YES];
NSNumber *buildingStreetNumber = [NSNumber numberWithInteger:10018];
數(shù)組
// 數(shù)組
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
names[]
字典
// 字典創(chuàng)建
NSDictionary *productManagers = @{@"iPhone": @"Kate", @"iPad": @"Kamal", @"Mobile Web": @"Bill"};
// 訪問
NSString *product = productManagers[@"iPhone"];
//
NSMutableDictionary *user = [NSMutableDictionary dictionary];
// 設(shè)置
user[@"name"] = @"Bob";
user[@"title"] = @"IT Manager";
user[@"age"] = @25;
// 迭代
[user enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"key : %@, value : %@", key, obj);
}];
CGRect 函數(shù)
使用
// Good!
CGRect frame = self.view.frame;
CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);
CGRect frame = CGRectMake(0.0, 0.0, width, height);
不使用
// Bad
CGRect frame = self.view.frame;
CGFloat x = frame.origin.x;
CGFloat y = frame.origin.y;
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;
CGRect frame = (CGRect){ .origin = CGPointZero, .size = frame.size };
注釋
當(dāng)需要注釋時(shí),注釋應(yīng)該用來解釋這段特殊代碼為什么要這樣做。任何被使用的注釋都必須保持最新或被刪除。
一般都避免使用塊注釋,因?yàn)榇a盡可能做到自解釋,只有當(dāng)斷斷續(xù)續(xù)或幾行代碼時(shí)才需要注釋。例外:這不應(yīng)用在生成文檔的注釋
空格
空行
6. 資源
iOS應(yīng)用包含多種資源文件
- storyboard/xib
- 圖片
- 字符串
- 字體
- 多媒體
storyboard/xib
圖片
字符串
字體
多媒體
7. 模塊
8. Xcode工程
物理文件應(yīng)該與Xcode工程文件保持同步來避免文件擴(kuò)張。任何Xcode分組的創(chuàng)建應(yīng)該在文件系統(tǒng)的文件體現(xiàn)。代碼不僅是根據(jù)類型來分組,而且還可以根據(jù)功能來分組,這樣代碼更加清晰。
盡可能在target的Build Settings打開"Treat Warnings as Errors,和啟用以下additional warnings。如果你需要忽略特殊的警告,使用 Clang's pragma feature。
9. 輔助工具
- Spacecommander
參考:
- 《蘋果Cocoa代碼規(guī)范》
- 《NYTimes Objective-C代碼規(guī)范》
- 《Effective Objective-C》
- 《raywenderlich.com Objective-C編碼規(guī)范》
- 《大規(guī)模C++編程》
- Robots & Pencils
- New York Times
- GitHub
- Adium
- Sam Soffes
- CocoaDevCentral
- Luke Redpath
- Marcus Zarra