iOS開發手冊

1.工程文件結構

  • 所有的文件應放在工程中的項目目錄下。
  • 項目文件和物理文件需保持一致。
  • Xcode創建的任何組(group)都必須在文件系統中有映射。
  • 項目文件不僅可以按照業務類型分組,也可以根據功能分組。

2.代碼格式規範

2.1 代碼註釋格式

  • 文件註釋:採用Xcode自動生成的註釋格式。

    //
    //  AppDelegate.h
    //  項目名稱
    //
    //  Created by 開發者姓名 on 2018/6/8.
    //  Copyright © 2018年 公司名稱. All rights reserved.
    //
  • import註釋:如果有一個以上的import語句,對這些語句進行分組,每個分組的註釋是可選的

    // Framework
    #import <UIKit/UIKit.h>
    
    // Model
    #import "WTUser.h"
    
    // View
    #import "WTView.h"
  • 方法註釋:Xcode8之後快捷鍵自動生成(option + command + /)。

    /**
    <#Description#>
    
    @param application <#application description#>
    @param launchOptions <#launchOptions description#>
    @return <#return value description#>
    */
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
  • 代碼塊註釋:單行的用 “// + 空格” 開頭, 多行用“/ /”。

    2.2 代碼結構與排版

  • 聲明文件:方法順序和實現文件的順序保持一致,根據需要用”#pragma mark -“將方法分組。
  • 實現文件:必須用”#pragma mark -“將方法分組。分組前後優先級:Lifecycle方法 > Public方法 > UI方法 > Data方法 > Event方法 > Private方法(邏輯處理等) > Delegate方法 > 部分Override方法 > Setter方法 > Getter方法。

#pragma mark - Lifecycle

- (instancetype)init {}
- (void)viewDidLoad {}
- (void)viewWillAppear:(BOOL)animated {}
- (void)viewDidAppear:(BOOL)animated {}
- (void)viewWillDisappear:(BOOL)animated {}
- (void)viewDidDisappear:(BOOL)animated {}
- (void)didReceiveMemoryWarning {}
- (void)dealloc {}

#pragma mark - Public

- (void)refreshData {}

#pragma mark - UI

- (void)initSubViews {}

#pragma mark - Data

- (void)initData {}
- (void)constructData {}

#pragma mark - Event

- (void)clickButton:(UIButton *)button {}

#pragma mark - Private

- (CGFloat)calculateHeight {}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {}

#pragma mark - Override

- (BOOL)needNavigationBar {}

#pragma mark - Setter

- (void)setWindow:(UIWindow *)window {}

#pragma mark - Getter

- (UIWindow *)window {}
```
  • 變量:優先使用屬性聲明而非變量聲明,注意屬性修飾符、變量類型、變量之間的間隔。

    @property (strong, nonatomic) UIWindow *window;
  • 點語法:應始終使用點語法來訪問和修改屬性。
  • 間距要求如下:

    • 一個縮進使用四個空格。
    • 在”-“或者”+“號之後應該有一個空格,方法的大括號和其它大括號始終和聲明在同一行開始,在新的一行結束,另外方法之間應該空一行。
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        if (door.isClosed) {
            // Do something
        } else {
            // Do something
        }
        return YES;
    }
  • 長度要求如下:

    • 每行代碼的長度不應該超過100個字符。
    • 單個函數或方法的實現代碼控制在50行以內。
    • 單個文件裏的代碼行數控制在500~600行之內。

3.代碼命名規範

3.1 代碼命名基礎

  • 最好是既清晰又簡短,但不要爲簡短喪失清晰性,並使用駝峯命名法。
  • 名稱通常不縮寫,即使名稱很長也要拼寫完全(禁止拼音),然而可使用少數非常常見的縮寫,部分舉例如下:

    常用縮寫詞 含義 常用縮寫詞 含義
    app application max maximum
    alt alternate min minimum
    calc calculate msg message
    alloc allocte rect rectangle
    dealloc deallocte msg message
    init initialize temp temporary
    int integer func function
  • 由於Cocoa(Objective-C)沒有C++一樣的命名空間機制,需添加前綴(公司名首字母)防止命名衝突,前綴使用2個字符(以下統稱項目前綴)。
  • 常見的單詞略寫:ASCII,PDF,HTTP,XML,URL,JPG,GIF,PNG,RGB

3.2 類和協議命名

  • 類名應明確該類的功能,並且要有項目前綴防止命名衝突。
  • 協議組合一組方法作爲一個類的部分接口使用, 用類名作爲協議名,例如:NSObject。
  • 協議僅僅組合一組方法而不關聯具體類,這種協議的命名應採用動名詞形式(ing)。
  • 委託形式的協議命名爲類名加上Delegate,例如:UIScrollViewDelegate。

3.3 變量和屬性命名

  • 變量名應前置下劃線“_”,屬性名沒有下劃線。
  • 屬性本質上是存取方法setter/getter,可進行重寫(注意內存管理)。

    @property (strong, nonatomic) UIWindow *window;
    - (void)setWindow:(UIWindow *)window;
    - (UIWindow *)window;
  • 可以適當的對setter/getter進行別名設置。

@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled; 
```

3.4 方法和函數命名

  • 方法名和函數名一般不需要前綴,但函數(C語言形式)作爲全局作用域的時候最好加上項目前綴。
  •  表示行爲的方法名稱以動詞開頭,但不要使用do/does等無實際意義的助動詞。
  • 參數前面的單詞要能夠描述該參數,並且參數名最好能用描述該參數的單詞命名。

    - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
  • 方法中多個參數可以使用適當的介詞進行連接。

// 後續多個參數使用with
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
//  添加適當介詞能夠使方法的含義更明確
- (BOOL)lockWhenCondition:(NSInteger)condition beforeDate:(NSDate *)limit;
// 第一個參數用了with,後面的參數不使用with
- (instancetype)initWithImage:(nullable UIImage *)image highlightedImage:(nullable UIImage *)highlightedImage;
```
  • 只有在方法返回多個值的時候使用get單詞進行明確。

    - (void)getLineDash:(nullable CGFloat *)pattern count:(nullable NSInteger *)count phase:(nullable CGFloat *)phase;
  • 方法返回某個對象實例。

// 類方法創建對象
+ (instancetype)buttonWithType:(UIButtonType)buttonType;
// 單例命名
+ (UIApplication *)sharedApplication; 
```
  • 委託或代理方法命名第一個參數最好能相關某個對象。

    - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
  • 私有方法不要以下劃線“_“開頭,因爲系統私有方法保留此方式。
  • 自定義方法和系統方法重名,建議在方法開頭加前綴”xx_methodName“。

    3.5 常量和宏的命名

  • const常量外部聲明:在Objective-C文件中優先採用FOUNDATION_EXTERN和UIKIT_EXTERN,而非C語言中的extern。
  • const常量採用駝峯命名原則。
  • const常量根據作用域適當加上前綴(含項目前綴):可供外部使用需加上相應的類名或者模塊前綴,僅文件內部使用需要加上小寫字母“k”.
  • 宏定義每個字母採用大寫,單詞之間用下劃線“_”間隔。
  • 宏定義也可根據作用範圍加上適當前綴,避免命名衝突。

    3.6 枚舉的命名

  • 使用枚舉來定義一組相關的整數常量,增強代碼的可讀性。
  • 枚舉可根據作用域添加前綴(含項目前綴),格式:[相關類名或功能模塊名] + [描述] + [狀態]。
  • 建議優先採用Objective-C的聲明NS_ENUM和NS_OPTIONS,少採用C語言形式的enum等枚舉聲明.
  • 枚舉定義時需指定None狀態,並且其rawValue一般爲起始值0。

// NS_ENUM
typedef NS_ENUM(NSInteger, UIStatusBarAnimation) {
    UIStatusBarAnimationNone    = 0,
    UIStatusBarAnimationFade    = 1,
    UIStatusBarAnimationSlide   = 2,
}
typedef NS_OPTIONS(NSUInteger, UIRemoteNotificationType) {
    UIRemoteNotificationTypeNone    = 0,
    UIRemoteNotificationTypeBadge   = 1 << 0,
    UIRemoteNotificationTypeSound   = 1 << 1,
    UIRemoteNotificationTypeAlert   = 1 << 2,
    UIRemoteNotificationTypeNewsstandContentAvailability = 1 << 3,
}
```

3.7 通知命名

  • 外部聲明:在Objective-C文件中優先採用FOUNDATION_EXTERN和UIKIT_EXTERN,而非C語言中的extern。
  • 通知的命名一般都是跨文件使用的,需添加項目前綴。

    // [相關聯類名或者功能模塊名] + [will/Did](可選) + [描述] + Notification
    UIApplicationDidEnterBackgroundNotification       
    UIApplicationWillEnterForegroundNotification      

3.8 類型別名命名

  • 根據作用域添加前綴(含項目前綴),格式:[類名或功能模塊名] + [描述]。

4.文件資源命名規範

  • 資源文件命名也需加上項目前綴。
  • 資源文件名全小寫,單詞之間用下劃線“_”間隔。
  • 資源文件命名格式:[項目前綴] + [業務] + [文件名]
  • 圖片文件命名格式:[項目前綴] + [業務] + [類型] + [狀態]。

    // 常見類型:logol,icon,img
    // 常見狀態:normal,selected,highlight
    UIImage *image = [UIImage imageNamed:@"wt_setting_icon_normal"];

5.代碼警告處理

  • 注意警告問題的隱蔽性,因此最好修復警告。
  • 警告類型的查看步驟:選中警告 -> 右鍵Reveal in Log(不編譯Reveal in Log是灰色的,因此先編譯) ->查看方括號的內容
  • 如果需要忽略警告,建議優先代碼push或者pop處理。

    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-retain-cycles"
    // 造成警告的代碼
    #pragma clang diagnostic pop
  • 如果警告數量過大,檢查警告類型以及必要性,可xcode配置忽略此類型警告。步驟:選中工程 -> TARGETS -> Build Settings -> Other Warning Flags

    忽略單個和全局配置稍有差別,如下舉例:
    push/pop    Other Warning Flags
    -Wformat —-> -Wno-format 
    -Wunused-variable —-> -Wno-unused-variable 
    -Wundeclared-selector —-> -Wno-undeclared-selector 
    -Wint-conversion —-> -Wno-int-conversion
  • 也可以在pch等大範圍作用域的頭文件中添加代碼來忽略後續警告:#pragma clang diagnostic ignored “警告名稱” 。

6.外部庫文件引入

  • 庫文件引入最好把警告處理掉。
  • 庫文件引入優先採用CocoaPods引入,並且指定版本號。
  • 源文件方式需引入文件到工程目錄下。
    圖例
  • 源文件方式需注意有無版本說明信息(可能在README文件中,也可能在某個.h頭文件中,又或者有Version文件)沒有時需在庫文件目錄下新增版本說明文件,

7.代碼版本管理

  • 版本管理工具:svn 或 git。
  • svn文件管理配置:目錄~/.subversion打開config文件配置global-ignore。
  • git文件管理配置:.gitignore文件記錄了被git忽略的文件,作用於本倉庫,常見語法如下:

    • 井號(#)用來添加註釋用的,比如 "#註釋"。
    • build/ : 星號()是通配符,build/*則是要說明要忽略 build 文件夾下的所有內容。
    • *.pbxuser : 表示要忽略後綴名爲.pbxuser的文件。
    • !default.pbxuser : 感嘆號(!)是取反的意思,*.pbxuser 表示忽略所有後綴名爲.pbxuser的文件,如果加上!default.pbxuser則表示,除了default.pbxuse忽略其它後綴名爲pbxuse的文件。
  • 提交信息規範:

    • BUG類型爲“Fix + [BUG編號] + [BUG描述]”。
    • 任務類型爲“Done + [任務編號] + [任務描述]”。
    • 任務中間態爲“Doing + [任務編號] + [任務描述]”。
    • 引入類庫爲“import + [類庫名]”。

8.構建和分發

  • 手動構建:Xcode構建注意證書配置。
  • 自動化構建:Jenkins+Fastlane、xcodebuild
  • 內側分發渠道:fir.im蒲公英等。
  • 線上渠道:AppStore。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章