當你試圖解決一個別人代碼中的問題時,難得不是怎么解決這個問題,而是先得找到、讀懂這段代碼。
推薦文檔:https://github.com/raywenderlich/swift-style-guide#naming
一:工程目錄結構規范
1、除了注釋外,所有的資源命名都用英文,不要用魔術數字、漢字。
2、推薦一個規范的工程目錄結構
Macro['m?kro]:存放公用頭文件比如:URL,宏定義,通知,枚舉等等。
Storage['st?r?d?]:存放封裝HTTP請求和數據庫操作文件。
Resources[ris?rsiz]:存放html、音頻、視頻、圖片等資源文件。
Extra['?kstr?]:存放第三方SDK,如:百度地圖SDK,支付寶SDK等等
Vendors['v?nd?z]:存放工程中封裝的一些公用方法 或 SDK。
Control[k?n'trol]:存放網絡請求(HTTP)Manager、數據庫(DB)操作等類文件。
View[vju]:存放所有自定義界面View。
Model['mɑdl]:負責解析HTTP下來的數據。
Controller[k?n'trol?]:存放所有控制器類。
3、所有的ViewController都應繼承自一個BaseViewController(大家懂的)。
4、文件命名、類名應以相應模塊英文單詞為準,不要用魔術數字命名,比如:
5、StoryBoard使用:界面跳轉用代碼實現,不建議用拖關系線條,方便后期維護。
6、界面適配,建議用 AutoLayout 放棄 Autoresizing,隨著大屏iPhone推出,蘋果主推 AutoLayout 技術。
8、所有的類名和邏輯方法,要加注釋。
9、所有的公用方法,都抽成一個公用類里。
10、不要用虛擬目錄,如果需要在工程中添加新的文件夾,使用 Add File To 方法添加。
11、推薦一個 ViewController 注釋模板
// MARK: - LifeCycle
override func viewDidLoad() {
? ? super.viewDidLoad()
}
// MARK: -?Intial Method
// MARK: - HTTP Method
// MARK: -?Action Method
// MARK: -?Private Method
// MARK: -?UITableViewDataSource
// MARK: -?UITableViewDelegate
// MARK: -?CustomDelegate
// MARK: -?Target Method
// MARK: -?Setter Getter Method
二:代碼規范
1、盡可能使你的工程中不要出現代碼警告,因為警告過多時也會造成一些未知錯誤。對于第三方庫中的警告,你也應該積極清除掉。
2、Delegate方法名稱
建議:使用參數標簽,并且在第一個參數使用下劃線( _ )來代替一個明確的參數標簽
func namePickerView(_ namePickerView: NamePickerView, didSelectName name: String)
func namePickerViewShouldReload(_ namePickerView: NamePickerView) -> Bool
不建議:
func didSelectName(namePicker: NamePickerViewController, name: String)
func namePickerShouldReload() -> Bool
3、屬性賦值
建議:
let selector = #selector(viewDidLoad)
view.backgroundColor = .red
let toView = context.view(forKey: .to)
let view = UIView(frame: .zero)
不建議:
let selector = #selector(ViewController.viewDidLoad)
view.backgroundColor = UIColor.red
let toView = context.view(forKey: UITransitionContextViewKey.to)
let view = UIView(frame: CGRect.zero)
4、類、函數注釋
給類加名稱注釋有很大的幫助,我們往往知道一個頁面的 title,卻不知道這個頁面在工程中對應的類(尤其是當你要修改小伙伴寫的代碼)。如果你的小伙伴,給他的類加了名稱注釋,根據名稱在工程中全局搜索,你將能很快搜到這個類。
// 首頁
class HomeViewController: UIViewController {
// class stuff here
}
5、if語句
建議:
if user.isHappy {
// Do something
} else {
// Do something else
}
不建議:
if user.isHappy
{
// Do something
}
else {
/ Do something else
}
6、變量聲明
建議:
var data = ["A": 1.2, "B": 3.2]
不建議:
var data :[String:CGFloat] = ["A" : 1.2, "B":3.2]
var data : [String:CGFloat] = ["A" : 1.2, "B":3.2]
7、方法聲明
func reticulateSplines(spline: [Double]) -> Bool {
// reticulate code goes here
}
如果函數參數較多,使用換行表示
func reticulateSplines(spline: [Double],
? ? ? ? ? ? ? ? ?adjustmentFactor: Double,
? ? ? ? ? ? ? ? ?translateConstant: Int, comment: String) -> Bool {
? ? ? ? ? ? ? ? // reticulate code goes here
}
8、聲明變量
建議:Swift有類型推斷機制,可以根據初始化賦值的類型推斷出變量、常量的值
let width = 120.0? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // Double
let widthString = (width as NSNumber).stringValue? ? // String
不建議:
let width: NSNumber = 120.0? ? ? ? ? ? ? ? ? ? ? ? ? // NSNumber
let widthString: NSString = width.stringValue? ? ? ? // NSString
9、調用方法
建議:
if let textContainer = self.textContainer {
// do many things with textContainer
}
不建議:
self.textContainer?.textLabel?.setNeedsDisplay()
10、嵌套if語句
建議:
var subview: UIView?
var volume: Double?
if let subview = subview, let volume = volume {
// do something with unwrapped subview and volume
}
不建議:
var optionalSubview: UIView?
var volume: Double?
if let unwrappedSubview = optionalSubview {
? ? if let realVolume = volume {
? ? ? ? // do something with unwrappedSubview and realVolume
? ? }
}
11、定義空數組
建議:
var names: [String] = []
var lookup: [String: Int] = [:]
不建議:
var names = [String]()
var lookup = [String: Int]()
13、數組
建議:
var deviceModels: [String]
var employees: [Int: String]
var faxNumber: Int?
不建議:
var deviceModels: Array<String>
var employees: Dictionary<Int, String>
var faxNumber: Optional<Int>
14、閉包
建議:
resource.request().onComplete { [weak self]
response in
guard let this = self else {
? ? return
}
let model = this.updateModel(response)
this.updateUI(model)
}
不建議:
resource.request().onComplete { [unowned self] response in
let model = self.updateModel(response)
self.updateUI(model)
}
resource.request().onComplete { [weak self] response in
let model = self?.updateModel(response)
self?.updateUI(model)
}
15、循環語句
建議:
for _ in 0..<3 {
print("Hello three times")
}
for (index, value) in dataArray.enumerated() {
print("\(value) is at position #\(index)")
}
for index in stride(from: 0, to: dataArray.count, by: 2) {
print(index)
}
for index in dataArray.reversed() {
print(index)
}
不建議:
var i = 0
while i < 3 {
print("Hello three times")
i += 1
}
var i = 0
while i < attendeeList.count {
let person = attendeeList[i]
print("\(person) is at position #\(i)")
i += 1
}
16、分號(在Swift中不用給每個語句后面加分號,換行代表這條語句結束,如果兩條語句寫在同一行,則必須在第一條語句后加分號,但不建議這種寫法)
建議:
let swift = "not a scripting language"
不建議:
let swift = "not a scripting language";
17、if語句
建議:
if name == "Hello" {
print("World")
}
不建議:
if (name=="Hello") ?{
print("World")
}
18、在寫代碼時,應該遵循面向對象六大原則
1、單一職責原則(SRP):一個類應該只有一個發生變化的原因。
2、開放封閉原則(OCP):對擴展是開放的,而對修改是封閉的。
3、Liskov替換原則(LSP):主要是通過抽象和多態來實現,而抽象和多態的實現又來自繼承。
4、依賴倒置原則(DIP):針對接口編程,而不是針對實現編程。
5、接口隔離原則(ISP):使用多個隔離的接口,比使用單個接口要好。
6、迪米特原則(LOD):一個實體應當盡量少的與其他實體之間發生相互作用,使得系統功能模塊相對獨立。
19、常用CGRect方法
let greenView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
// 獲取view的最小X值,也就是這個view的X值
let minX: CGFloat = greenView.frame.minX
// 獲取view的最大的X值,也就是這個view的X值+view的寬
let maxX: CGFloat = greenView.frame.maxX
// 獲取view的最小Y值,也就是這個view的Y值
let minY: CGFloat = greenView.frame.minY
// 獲取view的最大Y值,也就是這個view的Y值+view的高度
let maxY: CGFloat = greenView.frame.maxY
// 獲取view的中點X
let midX: CGFloat = greenView.frame.midX
// 獲取view的中點Y
let midY: CGFloat = greenView.frame.midY
20、協議:如果一個類中的協議太多時,可以用 extension 去實現協議
建議:
class MyViewController: UIViewController {
// class stuff here
}
// MARK: - UITableViewDataSource
extension MyViewController: UITableViewDataSource {
// table view data source methods
}
// MARK: - UIScrollViewDelegate
extension MyViewController: UIScrollViewDelegate {
// scroll view delegate methods
}
不建議:
class MyViewController: UIViewController, UITableViewDataSource, UIScrollViewDelegate {
// all methods
}
21、工程中我們常用的是MVC目錄(Controller、Model、View),為了好區分模塊,我們又會在每個目錄下創建功能目錄文件夾,比如在Controller下創建Home(主頁)、Order(訂單)、Me(個人中心),依次類推,當模塊較多時,這樣也會導致工程看起來很亂。此時,我們可以這樣劃分:在每個功能目錄下創建MVC目錄(Controller、Model、View),這樣把MVC細分到每個功能,這樣就更簡單了。