# Model

## เริ่มจากโมเดลกันก่อน

ให้เราสร้างไฟล์ใหม่ ด้วยการ**คลิ๊กขวา**ที่โฟลเดอร์ **TodoApp** ใน Project navigator เลือก New File...

![](https://1168329629-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LGk7Utff0rVWsqK4eYO%2F-LGndSy4u819Dt-32OG-%2F-LGndgCdxbYq9HrDnFom%2FScreen%20Shot%202018-07-07%20at%2014.28.13.png?alt=media\&token=be17c6ae-91d9-41e6-8711-1bfa033c7890)

จากนั้นเลือก Swift File กด Next

![](https://1168329629-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LGk7Utff0rVWsqK4eYO%2F-LGndSy4u819Dt-32OG-%2F-LGndjNNPYKAHzImWSpm%2FScreen%20Shot%202018-07-07%20at%2014.29.20.png?alt=media\&token=87575f6a-0e81-4752-817f-e4de2db51359)

ตั้งชื่อไฟล์เป็น Todo แล้วกด create

![](https://1168329629-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LGk7Utff0rVWsqK4eYO%2F-LGndSy4u819Dt-32OG-%2F-LGndtILdqzW3MbjhMNJ%2FScreen%20Shot%202018-07-07%20at%2014.29.50.png?alt=media\&token=207b8e78-f855-41be-9439-8b26c8a05151)

Xcode จะแสดงไฟล์ที่เพิ่งสร้างให้เรา

![](https://1168329629-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LGk7Utff0rVWsqK4eYO%2F-LGndSy4u819Dt-32OG-%2F-LGne10NNEOwsxh5M1Dj%2FScreen%20Shot%202018-07-07%20at%2014.32.16.png?alt=media\&token=c6ba154a-cf5b-4634-ad5a-9059f916a13b)

## Todo.swift

ให้เราเขียนโค้ดดังนี้

{% code title="Todo.swift" %}

```swift
import Foundation

class Todo {
    private var items = [TodoItem]()

    var totalItems: Int {
        return items.count
    }

    func item(at index: Int) -> TodoItem {
        return items[index]
    }

    func add(item: TodoItem) {
        items.insert(item, at: 0)
    }

    func remove(at index: Int) {
        items.remove(at: index)
    }
    
    func index(of item: TodoItem) -> Int? {
        return items.index(where: { (todoItem) -> Bool in
            return todoItem === item
        })
    }
    
    func move(from sourceIndex: Int, to destinationIndex: Int) {
        let item = items.remove(at: sourceIndex)
        items.insert(item, at: destinationIndex)
    }
}

class TodoItem {
    var title: String
    var isDone: Bool

    init(title: String, isDone: Bool) {
        self.title = title
        self.isDone = isDone
    }

    func toggleIsDone() {
        self.isDone = !self.isDone
    }
}
```

{% endcode %}

**บรรทัดที่ 3 - 27** เป็นการประกาศ Class Todo ที่เก็บรวบรวม TodoItem\
**บรรทัดที่ 29 - 41** เป็น Class TodoItem

**บรรทัดที่ 6 - 8** เรียกว่า **compute property** สามารถ get ค่าได้อย่างเดียวไม่สามารถ set ค่าได้เนื่องจากไม่สามารถเก็บค่าไว้ได้ โดยเมื่อเรียกจะได้จำนวน TodoItem ที่เก็บไว้ใน items กลับไป

**บรรทัดที่ 10 - 12** เป็นการประกาศฟังก์ชั่นที่รับ Int และคืนเป็น TodoItem ใช้ในการ get TodoItem ที่เก็บไว้ใน items ตาม index ที่ระบุ

**บรรทัดที่ 14 - 16** เป็นการประกาศฟังก์ชั่นที่รับ TodoItem ใช้ในการเก็บ TodoItem เพิ่ม โดยเพิ่มลงไปใน index ที่ 0 ของ items (Prepend)

**บรรทัดที่ 18 - 20** เป็นการประกาศฟังก์ชั่นที่ใช้ลบ TodoItem ตาม index ที่ระบุ

**บรรทัดที่ 22 - 26** เป็นการประกาศฟังก์ชั่นที่ใช้ในการหา index ของ TodoItem ที่อยู่ใน items

## TodoItem.swift

เนื่องจาก Todo.swift มีคลาส TodoItem ปนอยู่ด้วยจะเป็นการดีกว่าที่เราจะแยกมันออกมาเป็นอีกไฟล์นึงแทน ให้เราสร้างไฟล์ใหม่ชื่อ TodoItem.swift&#x20;

![](https://1168329629-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LGk7Utff0rVWsqK4eYO%2F-LGor07cfOhPrrTWdIDH%2F-LGosOOqGrKLwcF2DQSC%2FScreen%20Shot%202018-07-07%20at%2020.14.40.png?alt=media\&token=54f43d92-c599-4ef5-88d3-7a14e54fa21b)

แล้วย้ายโค้ดมาที่นี่

{% code title="TodoItem.swift" %}

```swift
import Foundation

class TodoItem {
    var title: String
    var isDone: Bool

    init(title: String, isDone: Bool) {
        self.title = title
        self.isDone = isDone
    }

    func toggleIsDone() {
        self.isDone = !self.isDone
    }
}
```

{% endcode %}

## ฟังก์ชั่นใน Swift (เพิ่มเติม)

```swift
// การประกาศฟังก์ชั่น
func functionName(externalLabel internalLabel: Type) -> Type {
    // external label จะเอาไว้ใช้ตอนเรียกฟังก์ชั่น
    // internal label จะเอาไว้ใช้ในฟังก์ชั่น
    // external และ internal เป็นอันเดียวกันได้โดยเขียนอันเดียว
    // type เป็น swift data type เช่น String, Int อื่น ๆ
    return internalLabel
}

// เวลาเรียกใช้งาน
let a = functionName(externalLabel: ค่า)

// หลายครั้งเราจะเห็นฟังก์ชั่นแบบ
func index(of item: TodoItem) -> Int? {
    return items.index(where: { (todoItem) -> Bool in
        return todoItem === item
    })
}
/* 
เราจะเรียกฟังก์ชั่นที่ไม่มีชื่อว่า Closure
{ (todoItem) -> Bool in
    return todoItem === item
}
*/
```

### การลดรูปฟังก์ชั่นใน Swift

```swift
func index(of item: TodoItem) -> Int? {
    return items.index(where: { (todoItem) -> Bool in
        return todoItem === item
    })
}
```

จากโค้ดนี้ในบรรทัดที่ 2 - 4 สามารถลดรูปได้แบบนี้

ตัด return ออก เนื่องจากมีโค้ดบรรทัดเดียว ผลลัพธ์บรรทัดนั้นจึงเป็นผลลัพธ์ของฟังก์ชัน

```swift
items.index(where: { (todoItem) -> Bool in
    todoItem === item
})
```

ตัด -> Bool ออก เนื่องจากเรารู้จากฟังก์ชั่น index แล้วว่าต้องรับ ฟังก์ชั่นที่ return Bool

```swift
items.index(where: { (todoItem) in
    todoItem === item
})
```

ตัด (todoItem) in ออกแทนที่ parameter แรกที่รับ ด้วย $0

```swift
items.index(where: { $0 === item })
```

ตัด (where: ) ออก parameter สุดท้ายถ้าเป็นฟังก์ชั่น สามารถละได้

```swift
items.index { $0 === item }
```
