|-業務1 | |-業務1的Storyboard | |-子業務1 | | |-controller | | |-view | | `-model | |-子業務2 | | |-controller | | |-views | | `-models |-業務2 | |-業務2的Storyboard | |-子業務1 | | |-controller | | |-view | | `-model | |-子業務2 | | |-controller | | |-view | | `-model |-util(工具) |-lib(第三方庫) |-ui(自定義的一些基礎view) |-Images.xcassets(xcode自帶圖片管理文件) `-Resources(資源文件,包括靜態文件,本地化文件等)
沒必要每行都加註釋,在3~10行左右的段落作註釋要好於每行都作註釋,顯而易見的代碼不加註釋。例如:數據庫
if (!returnValue){ //調用登陸過程失敗 ←無用的註釋 NSLog(@」登陸失敗」); }
括弧遵循緊湊編碼方式,以下:數組
for (int i = 0; i < 10 ; i++) { }
空格的使用xcode
關鍵字與其後的表達式之間要有空格,如:網絡
if (expr) 或 for (expr)
除「,「外,其它雙目操做符應與它們的操做數用空格隔開,如:架構
i=i+1; //錯誤的寫法,操做符兩端沒有空格 i = i + 1; //正確的寫法, if(a>b) //錯誤的寫法,邏輯判斷符號兩端沒有空格 if(a > b) //正確的寫法
資源文件的名字採用第一個單詞首字母小寫,其餘單詞首字母大寫的格式,最後以文件類型結尾,如:
contactImage:表明這是聯繫人圖片
contactInfoDB:表明這是聯繫人數據庫文件
contactLocalizable:表明這是聯繫人業務的本地化文件app
方法的名稱應所有使用有意義的單詞組成,且以小寫字母開頭,多單詞組合時,後面的單詞首字母大寫。如:ide
-(void)getContactInformation
設置類變量的內容的方法應使用set做爲前綴,讀取變量的內容的方法應使用get做爲前綴。如:函數
-(void)getContactName; -(void)setContactName:(NSString *)contactName;
方法中的參數:第一個參數名稱要從函數名稱上攜帶出來,第二個參數的首字母小寫,多個單詞組合時,後面單詞首字母大寫。參數有別名時,參數別名與參數名一致,但參數名前綴以_。參數別名與前一參數保留1個空格。參數無別名時,以有意義的字母命名。如:工具
-(void)myFunctionWithSizeA:(CGSize)sizeA sizeB:(CGSize)_sizeB;
變量必須起有意義的名字,使其餘組員能夠很容易讀懂變量所表明的意義,變量命名能夠採用同義的英文命名,可以使用幾個英文單詞,第一個單詞首字母小寫,其餘單詞首字母大寫。如:ui
NSString *contactName;
對於一些特殊類型的變量,命名時要帶上類型,如NSArray 的變量命名爲xxxArray,其餘的如xxxDictionary,xxxSize等。這樣就能夠從名稱上知道是什麼類型的變量。千萬不能將NSArray的變量命名爲xxxDictionary。
對於要和interface builder關聯的的輸出口變量,命名時要後綴以特定的控件名。如:
IBOutlet UILabel *contactNameLabel;
對於使用c語言形式聲明的變量,一些特定類型可採用必定的簡寫。如:
指針類型:P
結構體類型:Rec
數組類型:Arr
Core Graphic:CG
等。
循環控制變量一般使用單一的字符如:i、j、k等。使用有意義的名字,如objectIndex也是能夠的
枚舉變量也要有相應的前綴來區分不一樣的enum變量。好比蘋果公司的一個enum。如:
typedef enum CGPathDrawingMode CGPathDrawingMode; /* Drawing modes for text. */ enum CGTextDrawingMode { kCGTextFill, kCGTextStroke, kCGTextFillStroke, kCGTextInvisible, kCGTextFillClip, kCGTextStrokeClip, kCGTextFillStrokeClip, kCGTextClip };
常量的命名應當可以表達出它的用途,而且用大寫字母表示。如:
#define PI 3.1415926
一些常量前加特殊前綴,能夠做爲不一樣常量的區分,如:
UserDefaultsKey的變量前加UDKEY_, NotificationNameKey前面加NNKEY_, DictionaryKey前面加DICTKEY_
MBContactInfoView
,MBLabelView
等MBContactInfoViewController
,MBContactDetailViewController
等。UIViewController中儘可能不要出現直接設置控件(UIButton,UITextField等)屬性的代碼,而是將控件封裝在單獨的自定義UIView類中,而後在自定義UIView類中設置控件的屬性。以下的代碼最好不要在UIViewController中出現:
self.textLabel = [[UILabel alloc] init]; self.textLabel.textColor = [UIColor blackColor]; self.textLabel ... ... self.textLabel ... ... self.textLabel ... ...
initContent
和updateContent
方法,前者在viewDidLoad中調用,用來初始化全部的自定義UIView,後者在viewWillAppear中調用,用來更新全部的自定義UIView。import UIKit class SwiftController: MBViewController { // 屬性 @IBOutlet weak var queryButton: UIButton! @IBOutlet weak var contentView: MBContentView! @IBOutlet weak var tableView: UITableView! var contactTitle:NSString? // 生命週期 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. // 與界面無關屬性的初始化 self.contactTitle = "This is Test" // 界面的初始化在統一的方法initContent中執行 self.initContent() } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) // 界面的更新在統一的方法updateCotent中執行 self.updateCotent() } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) // 添加對通知事件的觀察 NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("queryFinished:"), name: "queryFinished", object: nil) } override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) } override func viewDidDisappear(animated: Bool) { super.viewDidDisappear(animated) // 移除對通知事件的觀察 NSNotificationCenter.defaultCenter().removeObserver(self, name: "queryFinished", object: nil) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // tableView協議 func numberOfSectionsInTableView(tableView: UITableView) -> Int { // #warning Potentially incomplete method implementation. // Return the number of sections. return 5 } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // #warning Incomplete method implementation. // Return the number of rows in the section. return 10 } func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return String(format: "Section %d", section) } func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cellIdentifier : String = "cellIdentifier" var cell:UITableViewCell? = self.tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? UITableViewCell if cell == nil { cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: cellIdentifier) } cell?.textLabel?.text = String(format: "Cell %d", indexPath.row) cell?.detailTextLabel?.text = "Watch out!!! Something AWESOME is coming~~~" return cell! } // 事件響應 @IBAction func queryPressed(sender: AnyObject) { } func queryFinished(sender: AnyObject) { } // 私有方法 private func initContent() { // 若是須要設置多個屬性則爲每一個View封裝單獨的方法來進行View的初始化 self.initQueryButton() } private func updateCotent() { } private func initQueryButton () { self.queryButton.setTitle("Query", forState: UIControlState.Normal) self.queryButton.setTitle("Query...", forState: UIControlState.Disabled) } /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { // Get the new view controller using segue.destinationViewController. // Pass the selected object to the new view controller. } */ }
import UIKit class MBContentView: UIView { @IBOutlet var contentView: UIView! @IBOutlet var imageView: UIImageView! @IBOutlet var label: UILabel! /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. override func drawRect(rect: CGRect) { // Drawing code } */ // 生命週期 // 在該方法中初始化View required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) // 加載xib內容 NSBundle.mainBundle().loadNibNamed("ContentView", owner: self, options: nil) self.addSubview(self.contentView) // 在統一的initConstraint方法中添加約束 self.initConstraint() } override func layoutSubviews() { super.layoutSubviews() } // 私有方法 private func initConstraint(){ // OC 用 Masonry, Swift 用 SnapKit self.contentView.mas_makeConstraints { (MASConstraintMaker) -> Void in var make = MASConstraintMaker make.edges.equalTo().self // make.top.equalTo().self // make.bottom.equalTo().self // make.leading.equalTo().self // make.trailing.equalTo().self } } // 提供接口供ViewController調用 func setQueryResult(queryResult:MBQueryResult?) { self.label.text = queryResult?.contactName } }
數據的加工處理通常放在Form/Model中,以下:
-(void)setPoint:(NSString *)point{ if ([point isEqualToString:@"null"]){ _point = @"0"; }else{ _point = point; } }
若是須要用到多個Model中的部分屬性,則須要創建新的Model。
若是Portocol實現的方法不超過3個,能夠直接定義在協議相關的類中,以下:
@protocol XXXDelegate <NSObject> -(void)method1:(id)obj; -(void)method2:(id)obj; -(void)method3:(id)obj; @end @interface XXX : UIView<XXXDelegate> @property (weak, nonatomic) IBOutlet id<XXXDelegate>delegate; @end
超過3個則須要單獨創建協議類
若是Manager須要在應用的生命週期內一直存在,則實現成單例,單例實現方式以下:
class func shareInstance()->XXManager{ struct MBSingleton{ static var predicate:dispatch_once_t = 0 static var instance:XXManager? = nil } dispatch_once(&MBSingleton.predicate,{ MBSingleton.instance=XXManager() } ) return MBSingleton.instance! }
命名要和具體業務相關,禁止出現業務不明確的Manager
Manager不對數據進行加工處理,而是交由Form/Model來作,相似下面的代碼不能寫在Manager內部
if "zzz" == c.zzz { c.zzz = a.xxx+b.yyy } else { c.zzz = a.xxx }