> For the complete documentation index, see [llms.txt](https://frost.gitbook.io/iosbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://frost.gitbook.io/iosbook/ios/ios-book/ios-swift-coding-style.md).

# \[iOS] Swift Coding Style

## 命名規則

&#x20;       (1.)  Apple以**Camel Case (駝峰法)**&#x65B9;法命名, 除了第1個單字, 每個單字的開頭大寫.

&#x20;        ex:  宣告1個Button

```swift
  var theFirstButton = UIButton()    (O)
  var Thefirstbutton = UIButton()    (X)  
```

&#x20;   &#x20;

&#x20;        (2.)   名字要能夠念出來, 不要用縮寫.

&#x20;        ex:  宣告1個Button

```swift
  var theFirstButton = UIButton()    (O)
  var theFirstBtn = UIButton()       (X)  
```

&#x20;       &#x20;

&#x20;       (3.)   宣告array時, 用**s**結尾

&#x20;       ex:  宣告1個button array

```swift
  var buttons: [UIButton] = []        (O)
  var buttonList: [UIButton] = []     (X)  
```

&#x20;      (4.)  IBOutlet 元件的命名,  其變數結尾與元件型別有關

&#x20;      ex:  宣告1個IBOutlet button&#x20;

```swift
@IBOutlet weak var theFirstButton: UIButton!        (O)
@IBOutlet weak var theFirstTouch: UIButton!         (X)  
```

&#x20;      (5.)   IBAction function的命名,  其function結尾與事件有關

&#x20;      ex:  宣告1個IBOutlet button 的 touchUpInside function

```swift
@IBAction func theFirstButtonTouchUpInside(_ sender: UIButton) {       (O)
}   
```

&#x20;      (6.)   Singleton或共用的實體, 取名為shared

&#x20;      ex: 宣告一個Singleton Class

```swift
class SingletonClass {       
   static let shared = SingletonClass()
}
```

&#x20;        (7.)  Class與資料夾名稱以**Camel Case (駝峰法)**&#x65B9;法命名, **但第1個字也是大寫**

&#x20;        ex: 宣告一個 Class

```swift
class MyClass {       
}
```

&#x20;          (8.)  Function的命名盡量以動詞開頭, 參數越少越好, 1個Function只做單一的1件事情,&#x20;

&#x20;              內容越精簡且越有可讀性越好

&#x20;          ex:&#x20;

```swift
func updateUI() {  
    self.updateTitleLabel()  
    self.updateButtonColor()   
}

func updateTitleLabel() { 
  //只更新TitleLabel  
}

func updateButtonColor() {   
  //只更新ButtonColor     
}
```

&#x20;           (9.)  較短的命名若能解釋清楚, 勝過較長的命名

&#x20;               較短的命名若不能解釋清楚,  較長的命名更好

&#x20;         &#x20;

&#x20;           (10.)  統一的命名, 比如說跟更新UI有關的function都用update開頭, 方便搜尋

&#x20;            ex:&#x20;

```swift
func updateUI() {       
}

func updateTitleLabel() {       
}

func updateButtonColor() {       
}
```

&#x20;         (11.) Delegates命名, 第一個參數通常是delegate source

&#x20;ex:&#x20;

```swift
func myViewDidSelect(_ myView: MyView, name: String)                 (O)
func myViewShouldReload(_ myView: MyView) -> Bool                    (O)


func myView(name: String)                                            (X)
func myViewShouldReload() -> Bool                                    (X)

```

## 縮排

&#x20;(1.) 括號與換行

Swift推的:

```swift
if (isHappy) {
  // Do something
} else {
  // Do something else
}
```

&#x20;比較少人用的:&#x20;

(微軟推的, 仔細觀察apple 的 sample code, 偶而也會有這種style出現)

```swift
if (isHappy)
{
  // Do something
}
else 
{
  // Do something else
}
```

(2.)  冒號, 逗號後留一個空格

```swift
let names: [String: String] = ["developer": "frank", "team": "F&Z"]
```

(3.) -> 前後留一個空格

```swift
func myViewShouldReload() -> Bool  
```

&#x20;

(4.)  { 前留一個空格

```swift
if (isHappy) {
  // Do something
}
```

(5.)空白行

&#x20;    空白行是必要的, 代表一個邏輯的轉折

```swift
func myViewShouldReload() -> Bool {
   var number = 0
   var title = "myName"

   self.doSomething()
   self.doAnotherThing()
}
```

## 註解

(1.) 最好的註解就是不需要使用註解, 由命名上就能了解程式的意義, 有時讀註解比讀code更花時間, 也必須花額外時間去維護註解.&#x20;

(2.) TODO

```swift
if (isHappy) {
  // TODO: Do something
}
```

(3.) 警告特殊情形

```swift
if (isHappy) {
  // something will happen...
}
```

## Protocol 實作

**Preferred**:

```swift
class ViewController: UIViewController {
}

// MARK: - UITableViewDataSource
extension ViewController: UITableViewDataSource {
}

// MARK: - UIScrollViewDelegate
extension ViewController: UIScrollViewDelegate {
}
```

**Not Preferred:**

```swift
class MyViewController: UIViewController, UITableViewDataSource, UIScrollViewDelegate {
  // all methods
}
```

## 宣告

(1.)  宣告空白Array & Dictionary

**Preferred:**

```swift
var titles: [String] = []
var songs: [String: Int] = [:]
```

**Not Preferred:**

```swift
var titles = [String]()
var songs = [String: Int]()
```

&#x20;(2.) 使用structure儲存相關的變數

```swift
struct StoryboardID {
    static let viewController = "viewController"
    static let noteViewController = "noteViewController"
    static let newViewController = "newViewController"
}
```

(3.) 使用enum使參數變得有意義

```swift
enum payType :Int {
    case cash, card, other
}
```

## MVC  (Model, View, Controller)

&#x20;MVC為iOS App 開發最常用的架構, 但Apple 提到除了 view controller, 還可以另外建立 model controller 和 helper controller, 讓程式的分工更為清楚.

**(1.) Model Controller**&#x20;

&#x20;     負責實現 model 的相關功能. 比方你在做一個資料庫 App, 要處理 data的新增, 修改, 刪除, 查詢等動作, 可以另外定義一個dataController 實現來相關功能, 讓viewController更為精簡

**(2.) Helper Controller**&#x20;

&#x20;     負責特定的功能, 例如可以建立一個 NetworkController, 專門處理 App與後台溝通的部分

## Guard

&#x20;(1.) 利用guard 判斷tableview的cell

```swift
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
        guard cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as? MyCell else {
            fatalError("dequeueReusableCell failed")
        }
        
        cell.initWithData()

        return cell
}
```

(2.) 利用guard 一次判斷

```swift
func saveData(data: MyData?, name:String?) {
    guard data != nil,
        name != nil,
        name.count > 0 else {
            return
    }
    
    //do something here
}
```

## nil-coalescing operator

利用 `??`語法設定變數為nil時的預設值

```swift
let userName = userNameTextField.text ?? "unknown"          
```
