GB代碼規(guī)范
頭文件#import的順序(商量)
寫法模板
#import <系統(tǒng)庫>
#import <第三方庫>
#import "其他類"
盡量按照先系統(tǒng)類 第三方類 自己寫的類順序導入 中間不能有空格
建議的寫法
#import <UIKit/UIKit.h>
#import <Google/Analytics.h>
#import "GBOrderEmptyView.h"
不建議的寫法
#import "GBOrderEmptyView.h"
#import <UIKit/UIKit.h>
#import <Google/Analytics.h>
@Class的寫法
寫法模板
@class class1,class2;
建議的寫法
@class UIView,UIImage;
不建議的寫法
@class UIPress;
@class UIPressesEvent;
@Interface的寫法
寫法模板
@interface 類名 : 父類 <協(xié)議1, 協(xié)議2>
@interface和類名中間一個空格
類名后緊跟:之后空格加上父類協(xié)議之間用,空格分割
建議的寫法
@interface AppDelegate : UIResponder <UIApplicationDelegate, UITableViewDataSource>
不建議的寫法
@interface AppDelegate:UIResponder<UIApplicationDelegate,UITableViewDataSource>
@protocol的寫法
寫法的模板
@protocol 協(xié)議的名稱 <協(xié)議1, 協(xié)議2>
@potocol和協(xié)議的名稱有空格 協(xié)議的名稱和其他協(xié)議有空格 其他協(xié)議之間有空格
建議的寫法
@protocol UIResponderStandardEditActions <NSObject>
不建議的寫法
@protocol UIResponderStandardEditActions<NSObject>
@property的寫法
@property(關鍵詞, 關鍵詞) 類 *變量名稱;
關鍵詞用,空格分割 類前后空格
正確寫法
@property(strong, nonatomic) UIWindow *window;
不建議的寫法
@property (strong, nonatomic) UIWindow * window;
@property關鍵詞的使用
對象 strong
基本變量assign
XIB控件 代理 weak
字符串和block使用 copy
對于一些弱引用對象使用weak
對于需要賦值內存對象 copy
h頭文件方法寫法
寫法模板
@interface
方法的參數在一排顯示
方法之間保留一行
第一個方法和@interface保留空行
最后一個方法和@end保留空行
建議的寫法
@interface Text : NSObject
- (void)testFunction;
@end
錯誤寫法
@interface Text : NSObject
- (void)testFunction;
@end
聲明const的字符串
開頭用k標識
推薦k+模板名字首字母大寫+作用名稱 防止和其他的重復
比如:CartViewModel類需要聲明更新購物車列表的通知
kCVMNoticationUpdateCartList
如果是聲明Cell的重用字符
k+cell的名稱+identifier
比如: GBHomeItemTableViewCell的標識符
kGBHomeItemTableViewCellIdentifier
Const聲明字符串位置
如果是需要聲明在h里面讓其他的類用到需要在h聲明m實現(xiàn)
聲明
UIKIT_EXTERN NSString *const kNoticationUpdateCartList;
實現(xiàn)
NSString *const kNoticationUpdateCartList = @"kNoticationUpdateCartList";
對于如果導入是UIKit類就使用UIKIT_EXTERN 如果是Founction使用關鍵詞FOUNDATION_EXTERN
如果只在本類使用只用寫實現(xiàn) 不用寫聲明。
方法盡量控制最多五十行
一個方法內部最多五十行 如果超過就精簡代碼 就分開方法寫
方便之后進行熱修復 代碼重構
注釋一定要寫
自己管理的類一定注釋屬性用途 方法的用途 參數的說明
屬性如果設置默認值 一定注明默認值是什么
如果方法內部存在邏輯判斷 方法跳轉 一定注釋判斷用法 方法跳轉用法
除了初始化操作
其他聲明變量 賦值 判斷 應該注明注釋用途
不允許外接修改的屬性要設置readonly
大家平時設置屬性默認是可讀可寫 但是這樣容易對于別人造成誤解 以為可以賦值
對于只能獲取的屬性 一定寫readonly
頭文件引入的其他類 要使用@class
頭文件引入的類使用@class聲明不實用#import引入
可以防止互相引入 編譯失敗 不容易查找的BUG
造成的缺點
m文件還要#import 其他類調用這個類屬性也要#import對應的類
綜合來說寧愿自己多操作 也要防止這種循環(huán)引入的BUG的出現(xiàn)
pragma mark的使用
對于屬性的不同作用 比如設置顏色的 設置字體的 設置其他樣式 的可以進行分組
對于方法的作用分類 比如添加功能 刪除功能的
對于其他的代理方法 Get Set方法 Init初始化方法
BOOL類型屬性的聲明
屬性set不要帶is get要帶is
@property(nonatomic, assign, getter=isUserLogin) BOOL userLogin;
方法命名的規(guī)范
不能用init set 開頭進行命名
如果不是寫初始化方法不要用init進行開頭
如果不是屬性的set方法不要用set作為方法的前綴
{}的寫法
建議的寫法
if(YES) {
doing something
}
不建議的寫法
if(YES)
{
doing something
}
計算符號兩邊要有空格
比如 + - * / =等運算符左右有空格
建議的寫法
x = 1 + 2;
不建議的寫法
x=1+2;
控件命名的規(guī)范
對于命名一定不要簡寫 那篇很長的單詞 但是一些單詞就是簡寫的除外 比如WTO RMB
UILabel結尾加上Label;
UIImageView結尾記上ImageView
等等讓其他的編程人員看名字就知道變量的用法 和屬于什么控件
建議的寫法
@property(nonatomic, strong) UILabel *userNameLabel;
不建議的寫法
@property(nonatomic, strong) UILabel *name;
if判斷里面的條件要提取出來
對于if里面很多的判斷條件 要提取出來 方便之后進行斷點測試
建議的寫法
BOOL isTrue = 5 > 3;
if(isTrue) {
}
不建議的寫法
if(5 > 3){
}
enum的定義
對于歸屬所在的enum 要寫在對應的類
我們現(xiàn)在就全部enum放在一個文件 覺得和蘋果的編碼規(guī)范違背 并且分離代碼有點麻煩
使用NS_ENUM進行定義
建議的寫法
typedef NS_ENUM(NSUInteger, GBAppRunDeveloperMode) {
GBAppRunDeveloperModeDebug,
GBAppRunDeveloperModePreRelease,
GBAppRunDeveloperModeRelease
};
不建議的寫法
typedef enum {
GBAppRunDeveloperModeDebug,
GBAppRunDeveloperModePreRelease,
GBAppRunDeveloperModeRelease
}GBAppRunDeveloperMode;
對于初始化一定要使用類對應的初始化方法
比如UIView的對應初始化方法為
- (instancetype)initWithFrame:(CGRect)frame
UIViewController對應的為
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil
防止初始化用init new等沒經過系統(tǒng)進行設置一些默認的屬性 造成bug
對于聲明NSString const要對適應對應的模塊
比如系統(tǒng)的 NSNotificationName
typedef NSString *NSNotificationName NS_EXTENSIBLE_STRING_ENUM;
建議的寫法
typedef NSString *NSStringConfigProjectName;
FOUNDATION_EXPORT NSStringConfigProjectName const kConfigProjectPluginDebugBaseUrlString;
不建議的寫法
FOUNDATION_EXPORT NSString *const kConfigProjectPluginDebugBaseUrlString;
命名的一些推薦關鍵詞
steup with cart buy等等待完善
對于#define宏命名
單詞全部的大寫 單詞之間用_分割
建議的寫法
#define NS_AVAILABLE_IOS(_ios) CF_AVAILABLE_IOS(_ios)
不建議的寫法
#define NSAvailableIos(_ios) CF_AVAILABLE_IOS(_ios)
對象調用方法要留空格
建議的寫法
[[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]
不建議的寫法
[[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds]
對于只在m內部聲明的const 需要添加static
這個我覺得可以不加 但是無法看到蘋果的實現(xiàn) 所以不知道蘋果的規(guī)范怎么寫的
建議寫法
static NSStringInitCheckManger const KGoogleServerTestKey = @""
不建議的寫法
NSStringInitCheckManger const KGoogleServerTestKey = @""
對于局部的變量盡量的初始化
局部的變量要初始化 屬性有默認的值 所以我們不必須對于屬性進行初始化
我之前遇到的一個BUG就是int類型沒有初始化給我默認Nan造成崩潰
建議的寫法
int index = 0;
不建議的寫法
int index;
對于一些對象判斷是否賦值可以不進行初始化 但是對于一定不會為nil要進行初始化
變量名的規(guī)范
一定要使用駝峰的命名
建議的寫法
UNUserNotificationCenter *unCenter = [UNUserNotificationCenter currentNotificationCenter];
不建議的寫法
UNUserNotificationCenter *uncenter = [UNUserNotificationCenter currentNotificationCenter];
對于屬性的賦值
不要直接調用set方法
建議的寫法
unCenter.delegate = self;
不建議的寫法
[unCenter setDelegate:self];
對于NS_OPTIONS類型多個值用|連接不能用+
建議的寫法
UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound
不建議的寫法
UNAuthorizationOptionAlert+UNAuthorizationOptionBadge+UNAuthorizationOptionSound
block的命名規(guī)范
之前研究過很多的第三方的命名 對于蘋果官方的沒找到
有CallBack結尾 Complete結尾 Block結尾 還有CompletionHandle結尾的
我看到蘋果很多的結尾都是用CompletionHandle結尾
大部分命名是Block我們按照Block命名
建議的寫法
typedef void(DidUpdateViewCompletionHandle)(void)
錯誤寫法
typedef void(DidUpdateViewCallBack)
使用NSUserDefaults要先創(chuàng)建
因為我們用到NSUserDefaults無非是保存和讀取 事先的創(chuàng)建一個對象 可以精簡代碼
當執(zhí)行方法很多 用變量替換
建議的寫法
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setDouble:CFAbsoluteTimeGetCurrent() forKey:@"AppStartTime"];
不建議的寫法
[[NSUserDefaults standardUserDefaults] setDouble:CFAbsoluteTimeGetCurrent() forKey:@"AppStartTime"]
盡量少在initialize load方法做一些初始化的事情
影響程序的啟動
建議的做法
- (void)viewDidLoad {
[super viewDidLoad];
[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName : GBCOLOR(153, 153, 153, 1.0)} forState:UIControlStateNormal];
[[UITabBarItem appearance] setTitleTextAttributes: @{NSForegroundColorAttributeName : GBCOLOR(255, 129, 55, 1.0)} forState:UIControlStateSelected];
}
不建議的做法
+ (void)initialize {
[[UITabBarItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName : GBCOLOR(153, 153, 153, 1.0)} forState:UIControlStateNormal];
[[UITabBarItem appearance] setTitleTextAttributes: @{NSForegroundColorAttributeName : GBCOLOR(255, 129, 55, 1.0)} forState:UIControlStateSelected];
}
通知的移除
通知在dealloc要使用移除對象監(jiān)聽的方法
建議的寫法
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
不建議的寫法
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:name1 object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:name2 object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:name3 object:nil];
}
判斷不要放在一行
判斷放在一行也是可以的 但是我們還是要求正規(guī)一些 畢竟注明Apple的goto BUG
建議的寫法
if (!self.startPagesListInfo) {
return ;
}
不建議的寫法
if (!self.startPagesListInfo) return ;
對于我們取值和存值的key要定義一下
定義一下key 方便我們使用 并且方便之后改名字
建議的寫法
NSString startLoadString = @"startLoad";
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
[userDefault objectForKey:startLoadString]
[userDefault setObject:@() forKey:startLoadString]
不建議的寫法
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
[userDefault objectForKey:@"startLoad"]
[userDefault setObject:@() forKey:@"startLoad"]
方法的參數連接不能有空格
建議的寫法
- (BOOL)judgeStartLoadPageInTimeCurrentWithModel:(StartPageModel *)obj
不建議的寫法
- (BOOL)judgeStartLoadPageInTimeCurrentWithModel : (StartPageModel *)obj;
對于block的循環(huán)引用使用weakify 和strongify
建議的寫法
@weakify(self);
[@[] enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
@strongify(self);
}];
不建議的寫法
__weak typeof(self) weakSelf = self;
[@[] enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
__strong typeof(weakSelf) strongSelf = weakSelf;
}];
布局和設置約束的方法選擇
可以實現(xiàn)GBInitViewProtocol協(xié)議 執(zhí)行對應的方法
建議的寫法
#pragma mark - <GBInitViewProtocol>
- (void)gbInitView {
self.backgroundColor = GBCOLOR_WHITE;
[self addSubview:self.loadImageView];
}
- (void)gbAutoLayoutView {
[self.loadImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self).insets(UIEdgeInsetsZero);
}];
}
有利于其他人很方便查找當前界面布局和添加試圖的位置
屬性要盡量使用懶加載
我們一個界面有很多控件 利用懶加載可以美化代碼
所有的懶加載放在Getter的mark的下面
建議的寫法
#pragma mark - getter
- (UIImageView *)loadImageView {
if (!_loadImageView) {
_loadImageView = [[UIImageView alloc] init];
_loadImageView.image = [self imageWithScreen];
_loadImageView.contentMode = UIViewContentModeScaleAspectFill;
_loadImageView.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(loadImageTouchAction)];
[_loadImageView addGestureRecognizer:tap];
}
return _loadImageView;
}
推薦的界面框架
所有界面的控件元素獨立到另外的UIView
UIViewController只負責跳轉界面
新建UIView負責界面的顯示
VIewModel負責數據的請求和解析
APi負責請求
model負責后臺數據解析
other 負責樣式和其他處理
多使用字面量
字符串 @""
NSString *string = @"string";
NSNumber @()
NSNumber *number = @(1);
字典 @{}
NSDictionary *dictionary = @{@"name":@"123"};
數組 @[]
NSArray *array = @[@"321231",@"123"];
字典和數組的取值和存值
多用類型常量 少用#define
建議的寫法
static const NSTimeInterval kAnimationDuration = 0.3;
不建議的寫法
#define ANIMATION_DURATION 0.3
對于一些狀態(tài) 選項的使用枚舉
盡量少用根據數字判斷狀態(tài)少用字符串 數字判斷狀態(tài)
建議的寫法
typedef NS_ENUM(NSUInteger, HomeViewState) {
HomeViewStateNoData,
HomeViewStateFailure,
HomeViewStateItemList,
HomeViewStateBannerList
};
if(state == HomeViewStateNoData){
// 顯示沒數據
}else if(state == HomeViewStateFailure) {
// 顯示請求錯誤
}else if(state == HomeViewStateItemList) {
// 顯示商品的列表
}else if(state == HomeViewStateBannerList) {
// 顯示banner列表
}
不建議的寫法
if(state == 0){
// 顯示沒數據
}else if(state == 1) {
// 顯示請求錯誤
}else if(state == 2) {
// 顯示商品的列表
}else if(state == 3) {
// 顯示banner列表
}
多使用類族
比如我們需要創(chuàng)建一個類 有多個樣式
typedef NS_ENUM(NSUInteger, ZHCustomViewStyle) {
ZHCustomViewStyleRed,
ZHCustomViewStyleWhite
};
@interface ZHCustomView : UIView
+ (instancetype)customWithStyle:(ZHCustomViewStyle)style;
@end
#import "ZHCustomView.h"
#import "ZHCustomRedView.h"
#import "ZHCustomWhiteView.h"
@implementation ZHCustomView
+ (instancetype)customWithStyle:(ZHCustomViewStyle)style {
switch (style) {
case ZHCustomViewStyleRed: {
return [[ZHCustomRedView alloc] initWithFrame:CGRectZero];
}
break;
case ZHCustomViewStyleWhite:{
return [[ZHCustomWhiteView alloc] initWithFrame:CGRectZero];
}
break;
default:
break;
}
}
@end
ZHCustomRedView
#import "ZHCustomView.h"
@interface ZHCustomRedView : ZHCustomView
@end
#import "ZHCustomRedView.h"
@implementation ZHCustomRedView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor redColor];
}
return self;
}
@end
ZHCustomWhiteView
#import "ZHCustomView.h"
@interface ZHCustomWhiteView : ZHCustomView
@end
#import "ZHCustomWhiteView.h"
@implementation ZHCustomWhiteView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor whiteColor];
}
return self;
}
@end
類名加上前綴避免沖突
因為團隊的合作 可能會出現(xiàn)大家想到一樣的名字或者添加第三方庫引入和第三方庫名字一樣
盡量加上前綴。
如果只針對工程就使用工程的縮寫
比如自己個人的第三方庫就加上自己名字或者昵稱的縮寫
建議的寫法
@interface GBHomeViewController : NSObject
不建議的寫法
@interface HomeViewController : NSObject
提供全能的初始化方法
對于初始化參數有很多 但是不是一定全部使用的可以提供多個初始化方法
建議的寫法
- (instancetype)initWithFrame:(CGRect)frame;
- (instancetype)initWithPerson:(GBPersonModel *)person;
- (instancetype)initWithFrame:(CGRect)frame person:(GBPersonModel *)person;
不建議的寫法
- (instancetype)initWithFrame:(CGRect)frame person:(GBPersonModel *)person;
實現(xiàn)Description方便調試
這個不推薦自己手寫 可以使用Xcode插件自動生成 屬性越多會加重手寫代碼的長度
盡可能使用不可變的對象
對于OC存在很多可變的對象 比如NSMutableString NSMutableArray NSMutableDictionary等等
對于一些不允許改變的直接使用不可變對象
可以節(jié)省對象開支 還可以防止別人修改數據造成bug
建議的寫法
NSArray *sexList = @[@"男",@"女"];
不建議的寫法
NSMutableArray *sexList = [NSMutableArray arrayWithArray:@[@"男",@"女"]]
如果建議的使用Block和代理
我覺得代理可以用在寫控件需要數據源賦值 和一些事件回調的時候使用
我查閱了蘋果的block基本上都是執(zhí)行一個時間 需要異步回調就使用block
如果沒有主動執(zhí)行動作 而是監(jiān)聽異步的回調 建議用代理
建議的寫法
TestName *name = [[TestName alloc] init];
name.delegate = self;
[name searchText:text completionHandle:^(BOOL isExit) {
};
- (void)name:(TestName)name resultTextHaveChanged:(NSString *)text {
}
不建議的寫法
TestName *name = [[TestName alloc] init];
[name searchText:text completionHandle:^(BOOL isExit) {
};
name.resultTextHaveChanged = ^(NSString *text) {
};
記得Dealloc記得釋放
記得在Dealloc釋放注冊的通知和KVO的監(jiān)聽
不釋放容易造成內存釋放崩潰
養(yǎng)成習慣把按照方法功能到分類里面
對于一些有按照功能類型的方法劃分在一個分類里面 分類和之前類寫在同一個文件
建議的寫法
@interface GBPerson : NSObject
@end
@interface GBPerson (Friend)
// 朋友
- (void)addFriend:(GBPenson *)friend;
- (void)deleteFriend:(GBPenson *)friend;
@end
@interface GBPerson (Play)
// 娛樂
- (void)playSound;
- (void)playGame;
@end
不建議的寫法
@interface GBPerson : NSObject
// 朋友
- (void)addFriend:(GBPenson *)friend;
- (void)deleteFriend:(GBPenson *)friend;
// 娛樂
- (void)playSound;
- (void)playGame;
為第三方類添加分類添加前綴
比如為系統(tǒng)UIView添加分類Add的添加前綴
建議的寫法
@interface UIView (GB_Add)
- (void)gb_addCustomView:(CustomView *)customView;
@end
不建議的寫法
@interface UIView (Add)
- (void)addCustomView:(CustomView *)customView;
@end
盡量少在分類里面使用屬性
假設我們分類有一個只讀的字段 我們可以不使用屬性 可以使用方法
建議的寫法
@interface UIView (Add)
- (NSArray *)customViews;
@end
@implementation UIView (Add)
- (NSArray *)customViews {
return @[customView1,customView2];
}
@end
不建議的寫法
@interface UIView (Add)
@property(nonatomic, strong, readonly) NSArray *customViews;
@end
@implementation UIView (Add)
- (NSArray *)customViews {
return @[customView1,customView2];
}
@end
非要在自己類的分類添加讀寫的屬性 可以用語法糖
可以利用主類的私有變量
建議的寫法
@interface ZHCustomView : UIView
@end
@interface ZHCustomView (Add)
@property(nonatomic, copy) NSString *name;
@end
#import "ZHCustomView.h"
@implementation ZHCustomView {
NSString *_name;
}
@end
@implementation ZHCustomView (Add)
- (void)setName:(NSString *)name {
_name = name;
}
- (NSString *)name {
return _name;
}
@end
不建議的寫法
- (void)setName:(NSString *)name {
objc_setAssociatedObject(self, "name", name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name {
return objc_getAssociatedObject(self, "name");
}
對于給第三方和系統(tǒng)的類非要添加屬性 可以使用runtime状飞。
對于一些自己不確定的可以使用try catch
對于不知道后臺返回什么類型的 可以使用try catch
建議的寫法
int index = 0;
@try {
NSArray *array = obj[@"list"];
index = [array.firstObject intValue];
}
@catch {}
因為OC是運行時語法 可能array不一定是NSArray類型的
不建議的寫法
int index = 0;
NSArray *array = obj[@"list"];
if(array.count > 0) {
index = [array.firstObject intValue];
}
如果后臺返回list為字段 這段代碼就崩潰了 可以使用try catch也可以用Model庫 或者自己添加判斷
使用dispatch_once來創(chuàng)建單例
建議的寫法
+ (instancetype)sharedInstance {
static ZHCustomView* instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [ZHCustomView new];
});
return instance;
}
不建議的寫法
+ (instancetype)sharedInstance {
static ZHCustomView* instance = nil;
if(!instance) {
instance = [[ZHCustomView alloc] initWithFrame:CGRectZero];
}
return instance;
}
便利的寫法
如果只需要便利數組和字典的寫法用for in
建議的寫法
for(NSString *name in names) {
//
}
不建議的寫法
for(int i = 0; i < names.lenght ; i ++) {
NSString *name = names[i];
}
需要便利字典和數組的內容 并且需要索引用enumerator
建議的寫法
[names enumerateObjectsUsingBlock:^(NSString * _Nonnull name, NSUInteger idx, BOOL * _Nonnull stop) {
}];
不建議的寫法
for(int i = 0; i < names.lenght ; i ++) {
NSString *name = names[i];
}
如果想進行緩存使用NSCache不要使用NSDictionary進行緩存
建議的寫法
NSCache *cache = [[NSCache alloc] init];
[cache setObject:object forKey:key];
不建議的寫法
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setObject:object forKey:key];
尤達表達式
推薦:
if ([myValue isEqual:@42]) { ...
不推薦:
if ([@42 isEqual:myValue]) { ...
nil 和 BOOL 檢查
推薦
if(name) {
}
if (isMyFriend) {
}
不建議的寫法
if(name != nil) {
}
if(isMyFriend == YES) {
}
黃金大道
建議的寫法
if(name.lenght <= 0) {
return;
}
if(![name isEqualToString:@"zhanghang"]) {
return;
}
.....
不建議的寫法
if(name.lenght > 0) {
if([name isEqualToString:@"zhanghang"]) {
....
}
}
復雜的表達式
建議的寫法
BOOL nameContainsSwift = [sessionName containsString:@"Swift"];
BOOL isCurrentYear = [sessionDateCompontents year] == 2014;
BOOL isSwiftSession = nameContainsSwift && isCurrentYear;
if (isSwiftSession) {
// Do something very cool
}
不建議的寫法
if ([sessionName containsString:@"Swift"] && [sessionDateCompontents year] == 2014) {
// Do something very cool
}
三元運算符
推薦:
result = a > b ? x : y;
不推薦:
result = a > b ? x = c > d ? c : d : y;
當三元運算符的第二個參數(if 分支)返回和條件語句中已經檢查的對象一樣的對象的時候,下面的表達方式更靈巧:
推薦:
result = object ? : [self createObject];
不推薦:
result = object ? object : [self createObject];
錯誤處理
有些方法通通過參數返回 error 的引用秉氧,使用這樣的方法時應當檢查方法的返回值,而非 error 的引用。
推薦:
NSError *error = nil;
if (![self trySomethingWithError:&error]) {
// Handle Error
}
此外瓤漏,一些蘋果的 API 在成功的情況下會對 error 參數(如果它非 NULL)寫入垃圾值(garbage values)凿将,所以如果檢查 error 的值可能導致錯誤 (甚至崩潰)校套。
數組和字典最好指定元素的類型
建議的寫法
NSArray<NSString *> *names = [NSArray array];
不建議的寫法
NSArray *names = [NSArray array];
數組和字典的元素垂直寫
建議的寫法
NSArray *array = @[
@"a",
@"b",
@"b"
];
NSDictionary *dictionary = @{
@"a":@"",
@"b":@"",
@"c":@""
};
不建議寫法
NSArray *array = @[@"a",@"b",@"b"];
NSDictionary *dictionary = @{@"a":@"",@"b":@"",@"c":@""};