Model

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

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

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

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

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

Todo.swift

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

Todo.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
    }
}

บรรทัดที่ 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

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

TodoItem.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
    }
}

ฟังก์ชั่นใน 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

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

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

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

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

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

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

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

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

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

items.index { $0 === item }

Last updated