|-业务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 }