iOS中書寫代碼規範35條小建議

来源:http://www.cnblogs.com/tylerzhang/archive/2017/04/03/6662138.html
-Advertisement-
Play Games

1.精簡代碼, 返回最後一句的值,這個方法有一個優點,所有的變數都在代碼塊中,也就是只在代碼塊的區域中有效,這意味著可以減少對其他作用域的命名污染。但缺點是可讀性比較差 NSURL *url = ({ NSString *urlString = [NSString stringWithFormat: ...


1.精簡代碼, 返回最後一句的值,這個方法有一個優點,所有的變數都在代碼塊中,也就是只在代碼塊的區域中有效,這意味著可以減少對其他作用域的命名污染。但缺點是可讀性比較差

NSURL *url = ({ NSString *urlString = [NSString stringWithFormat:@"%@/%@", baseURLString, endpoint];

[NSURL URLWithString:urlString];

});

2.關於編譯器:關閉警告:

#pragma clang diagnostic push

#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

[myObj performSelector:mySelector withObject:name];

#pragma clang diagnostic pop

3.忽略沒用的變數

#pragma unused (foo)

明確定義錯誤和警告

#error Whoa, buddy, you need to check for zero here!

#warning Dude, don't compare floating point numbers like this!

4.避免迴圈引用

  • 如果【block內部】使用【外部聲明的強引用】訪問【對象A】, 那麼【block內部】會自動產生一個【強引用】指向【對象A】

  • 如果【block內部】使用【外部聲明的弱引用】訪問【對象A】, 那麼【block內部】會自動產生一個【弱引用】指向【對象A】

__weak typeof(self) weakSelf = self;

dispatch_block_t block = ^{

   [weakSelf doSomething]; // weakSelf != nil

// preemption, weakSelf turned nil

[weakSelf doSomethingElse]; // weakSelf == nil

};

最好這樣調用:

__weak typeof(self) weakSelf = self;

myObj.myBlock = ^{

__strong typeof(self) strongSelf = weakSelf;

if (strongSelf) {

     [strongSelf doSomething]; // strongSelf != nil

// preemption, strongSelf still not nil(搶占的時候,strongSelf 還是非 nil 的)

[strongSelf doSomethingElse]; // strongSelf != nil }

else { // Probably nothing... return;

}

};

5.巨集要寫成大寫,至少要有大寫,全部小寫有時候書寫不提示參數;

6.建議書寫枚舉模仿蘋果——在列出枚舉內容的同時綁定了枚舉數據類型NSUInteger,這樣帶來的好處是增強的類型檢查和更好的代碼可讀性,示例:

// 不推薦寫法

typedef enum{

    UIControlStateNormal       = 0,

    UIControlStateHighlighted  = 1 << 0,

    UIControlStateDisabled     = 1 << 1,

} UIControlState;

// 推薦寫法

typedef NS_OPTIONS(NSUInteger, UIControlState) {

    UIControlStateNormal       = 0,

    UIControlStateHighlighted  = 1 << 0,

    UIControlStateDisabled     = 1 << 1,

};

7.建議載入xib,xib名稱用NSStringFromClass(),避免書寫錯誤

// 推薦寫法

 [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([DXRecommendTagVCell class]) bundle:nil] forCellReuseIdentifier:ID];

// 不推薦寫法

 [self.tableView registerNib:[UINib nibWithNibName:@"DXRecommendTagVCell" bundle:nil] forCellReuseIdentifier:ID];

8.場景需求:在繼承中,凡是要求子類重寫父類的方法必須先調用父類的這個方法進行初始化操作;建議:父類的方法名後面加上NS_REQUIRES_SUPER; 子類重寫這個方法就會自動警告提示要調用這個super方法,示例代碼

// 註意:父類中的方法加`NS_REQUIRES_SUPER`,子類重寫才有警告提示

- (void)prepare NS_REQUIRES_SUPER;

9.建議書寫屬性名不要和系統一樣,避免發生莫名其妙的問題;特別註意的是label;屬性名不要寫成textLabel

10.項目中添加plist類型文件,不要命名為info.plist,以防止和系統自帶的文件重名,發生莫名其妙的問題;

11.如果控制器已經載入過,就不用再次載入,優化性能

if (vc.isViewLoaded) return;

12.id類型屬性不能用點語法,調用get方法只能用中括弧調用,[id 方法名],利用iOS9新特性泛型就可以; 比如數組;

@property (nonatomic,strong) NSMutableArray *topicsM;

13.如果不是屬性,儘量不要點語法,一個老程式員的建議;

14.使用第三方框架,儘量不要更改內部文件,而應該再次封裝,個性定製;

15.判斷if書寫方式

建議這樣寫

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

    if (indexPath.row == 0) return 44;

    if (indexPath.row == 1) return 80;

    if (indexPath.row == 2) return 50;

    return 44;

}

而不是

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

    if (indexPath.row == 0) {

        return 44;

    }else if (indexPath.row == 1){

        return 80;

    }else if (indexPath.row == 2){

        return 50;

    }else{

        return 44;

    }

}

16.接手一個新項目,快速的調試,查看某個模塊或者方法的作用,需要註釋掉一個方法,或者某個代碼塊,直接寫return;而不是全選,註釋掉;

比如:查看這個方法loadNewRecommendTags作用

- (void)loadNewRecommendTags

{

    return;

 

    [SVProgressHUD show];

    // 取消之前的任務

    [self.manager.tasks makeObjectsPerformSelector:@selector(cancel)];

    NSMutableDictionary *params = [NSMutableDictionary dictionary];

 

    params[@"a"] = @"tag_recommend";

    params[@"c"] = @"topic";

    params[@"action"] = @"sub";

    [self.manager GET:DXCommonUrlPath parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {

 

        self.recommendTag = [DXRecommendTag mj_objectArrayWithKeyValuesArray:responseObject];

        [self.tableView reloadData];

        [SVProgressHUD dismiss];

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        DXLog(@"%@",error);

        [SVProgressHUD dismiss];

    }];

}

17.在一個自定義的View中,或者自定義cell中,modal出一個控制器建議:

[UIApplication sharedApplication].keyWindow.rootViewController

代替

self.window.rootViewController,因為程式可能不止一個window,self.window可能不是主視窗;

18.建議:用CGSizeZero 代替 CGSizeMake(0,0);

CGRectZero代替CGRectMake(0, 0, 0, 0);

CGPointZero代替CGPointMake(0, 0)

19.監聽鍵盤的通知建議:

UIKIT_EXTERN NSString *const UIKeyboardWillChangeFrameNotification

而不是,下麵代碼;因為鍵盤可能因為改變輸入法,切換成表情輸入,切換成英文,那麼frame可能會變高,變矮,不一定會發出下麵這些通知,但是肯定會發上面的通知

UIKIT_EXTERN?NSString *const UIKeyboardWillShowNotification;

UIKIT_EXTERN?NSString *const UIKeyboardDidShowNotification;

UIKIT_EXTERN?NSString *const UIKeyboardWillHideNotification;

UIKIT_EXTERN?NSString *const UIKeyboardDidHideNotification;

20.發佈通知的字元串常量規範,建議模仿蘋果;如上鍵盤的通知的書寫,加上const 保證字元串不可更改,以Notification結尾,一看就知道是通知;應儘量保證可讀性,不要怕句子太長;

NSString *const buttonDidClickNotification = @"buttonDidClickNotification";

21.如果除數為0,iOS8以下會直接報錯,(NaN—>Not a Number)iOS9不會,所以應該判斷,比如伺服器返回圖片的寬高,按比例縮放,CGFloat contentH = textW * self.height / self.width;

22.如果聲明的屬性,只想使用的get方法,不使用set方法,並且不想讓外界更改這個屬性的值,那麼建議在括弧裡面加readonly;示例:

@property(nonatomic,readonly,getter=isKeyWindow) BOOL keyWindow;

23.如果屬性是BOOL類型,建議在括弧中重寫get方法名稱,以提高可讀性,示例代碼如上;

24.從系統相冊中取照片之前,應該判斷系統相冊是否可用,如果從相機中拍照獲取,要判斷相機是否可用

// 判斷相冊是否可以打開

if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;

 

// 判斷相機是否可以打開

if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) return;

25.在導航控制中,或它的子控制器,設置導航欄的標題應該用self.navigationItem.title = @“標題”而不建議self.title = @“標題”;

26.給cell設置分割線,建議用setFrame:通過設置它高度,設置分割線,而不推薦用給cell底部添加一個高度的UIView,這樣做增加了一個控制項,從性能上來講,不如用setFrame設置高度

27.大量操作圖層會可能造成應用很卡,給用戶體驗差,所以儘量不要操作圖層;比如設置按鈕圓角,比如給button設置圓角;

self.loginBtn.layer.cornerRadius = 5;

self.loginBtn.layer.masksToBounds = YES;

28.給分類擴充方法,建議加上首碼,比如第三方框架SDWebImage,這樣做跟系統的方法很容易區分開,減少了程式員之間的溝通成本,同理跟分類添加屬性(利用運行時),建議加首碼,以防止蘋果官方過一段時間添加了一模一樣的屬性名,比如給UITextField分類添加了placeholderColor這個屬性,萬一某天官方給placeholder擴充了這個命名一模一樣的屬性,那麼就不好了

29.凡是在storyboard或者xib中給某個控制項添加顏色,顏色對角線有分割線,表示可以設置透明度,如果給這個控制項設置透明度建議在這裡設置,而不是設置alpha,因為設置了alpha,那麼上面有文字也會隨著透明度變大,而變得不清楚;可以設置background -->other -->opacity

30.整形轉化成浮點型,不建議這麼寫 a / b 1.0,這樣寫是錯誤寫法,示例1.5 / 2 1.0;根據運演算法則,從作到右,0 1.0 == 0,而應該在前面寫1.0 1.5 /2;建議直接強轉;(double)a/b;

31.抽取方法,或者寫工具類,能寫類方法,儘量寫成類方法,減少了創建對象的步驟,比如給UIView擴充分類載入xib,viewWithXib;

32.耗時操作應該放在子線程,避免卡主主線程,比如計算文件大小,下載大文件,清除緩存;

33.聲明一個屬性,如果是對象,比如數組,不能以new單詞開始,否則直接報錯,因為new在OC中是生成一個對象的方法,有特殊含義;比如,

@property (nonatomic,strong) NSMutableArray *newTopicsM;

註意:如果newtopicsM是一個單詞(區別於駝峰標誌),這樣寫不會報錯;如果是基本數據類型則不會報錯,比如

@property (nonatomic,assign) int newNumber;

但是如果一定要寫new單詞開頭的屬性,那麼聲明屬性的時候,重寫getter方法名稱只不過使用getter方法的時候註意下

34.在自定義方法中,and這個詞的用法應該保留。它不應該用於多個參數來說明,就像initWithWidth:height以下這個例子:

- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;

而不應該

- (instancetype)initWithWidth:(CGFloat)width andHeight:(CGFloat)height;

35.建議POST請求參數字典的寫法,這樣比較裝逼~

// NSDictionaryOfVariableBindings這個巨集生成一個字典,這個巨集可以生成一個變數名到變數值映射的Dictionary,比如:

NSNumber * packId=@(2);

NSNumber *userId=@(22);

NSNumber *proxyType=@(2);

NSDictionary *param=NSDictionaryOfVariableBindings(packId,userId,proxyType);


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在代碼中使用 listView .addHeaderView(...) 方法可以在ListView組件上方添加上其他組件,並且連結在一起像是一個新組件。如果多次使用 .addHeaderView(...) ,則最先添加的組件在最上方,按添加的先後順序由上到下羅列。 此時listView 的 posi ...
  • 餅圖模塊, 詳細模塊控制項封裝 餅圖封裝分為三個控制項. 餅圖控制項 描述控制項 餅圖控制項(左)描述控制項(右)整合 圖為將兩個控制項包裝好了以後的樣子稱為BigBackgroundView控制項 BigBackgroundView控制項: BigBackground控制項中提供的方法 從方法可以看出只要傳入pieV ...
  • Web New Year, New Blog Day 10 - Using JetBrains Rider with a .NET Core Console Application JavaScript Interview Day # 1: How to create a Class Using R... ...
  • 防止連續點擊的實現方式有很多種,比如,在所有的onclick裡面加上防多次點擊的代碼,或者定義一個新的OnClickListener,在裡面加上防多次點擊的代碼,然後項目中的所有OnClickListener都用這個listener,當然還有一些其他的方式,這裡將介紹一種新的方式來實現,那就是aop ...
  • 參考: "深入理解Android之AOP" AOP雖然是方法論,但就好像OOP中的Java一樣,一些先行者也開發了一套語言來支持AOP。目前用得比較火的就是AspectJ了,它是一種幾乎和Java完全一樣的語言,而且完全相容Java(AspectJ應該就是一種擴展Java,但它不是像Groovy " ...
  • 關於講解UITabel View的使用 參照 鏈接 http://www.bubuko.com/infodetail-974265.html identifier 可以看到在創建cell的時候伴隨著一個identifier的綁定,這個identifier可以理解為這個cell標識,標識它屬於哪個重用 ...
  • 轉載請註明出處:http://www.cnblogs.com/cnwutianhao/p/6664293.html 應該是目前為止全網最詳細的GCM推送解析。 GCM官方解釋: https://developers.google.cn/cloud-messaging/?hl=zh-cn Send d ...
  • 通過更換代理解決 Android SDK 線上更新鏡像伺服器資源:大連東軟信息學院鏡像伺服器地址:http://mirrors.neusoft.edu.cn 埠:80北京化工大學鏡像伺服器地址:IPv4: http://ubuntu.buct.edu.cn/ 埠:80IPv4: http://u ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...