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.避免循環引用緩存
__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(),避免書寫錯誤ide
// 推薦寫法 [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<DXTopics *> *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<DXTopics *> *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);