GB代碼規(guī)范1.0

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":@""};
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市牧抵,隨后出現(xiàn)的幾起案子笛匙,更是在濱河造成了極大的恐慌,老刑警劉巖犀变,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妹孙,死亡現(xiàn)場離奇詭異,居然都是意外死亡获枝,警方通過查閱死者的電腦和手機蠢正,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來省店,“玉大人嚣崭,你說我怎么就攤上這事∨嘲” “怎么了雹舀?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長粗俱。 經常有香客問我说榆,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任签财,我火速辦了婚禮串慰,結果婚禮上,老公的妹妹穿的比我還像新娘唱蒸。我一直安慰自己邦鲫,他們只是感情好,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布油宜。 她就那樣靜靜地躺著掂碱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪慎冤。 梳的紋絲不亂的頭發(fā)上疼燥,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機與錄音蚁堤,去河邊找鬼醉者。 笑死,一個胖子當著我的面吹牛披诗,可吹牛的內容都是我干的撬即。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼呈队,長吁一口氣:“原來是場噩夢啊……” “哼剥槐!你這毒婦竟也來了?” 一聲冷哼從身側響起宪摧,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤粒竖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后几于,有當地人在樹林里發(fā)現(xiàn)了一具尸體蕊苗,經...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年沿彭,在試婚紗的時候發(fā)現(xiàn)自己被綠了朽砰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡喉刘,死狀恐怖瞧柔,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情睦裳,我是刑警寧澤造锅,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站推沸,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜鬓催,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一肺素、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宇驾,春花似錦倍靡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至筝尾,卻和暖如春捡需,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筹淫。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工站辉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人损姜。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓饰剥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親摧阅。 傳聞我的和親對象是個殘疾皇子汰蓉,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內容