Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> iOS

วิธีเรียกเมธอดหลังหน่วงเวลา (Delay) ใน Swift/iOS

หน่วงเวลาการเรียกฟังก์ชันใน Swift 2 วิธี

บทความนี้สาธิต 2 วิธีหลัก: DispatchQueue.asyncAfter (แนะนำ) และ Timer


วิธีที่ 1: DispatchQueue.asyncAfter (Modern & Recommended)

func functionOne() {
    print("one")
    
    let delayTime = DispatchTime.now() + 3.0 // 3 วินาที
    DispatchQueue.main.asyncAfter(deadline: delayTime) {
        hello()
    }
}

func hello() {
    print("text")
}

functionOne()
// Output: "one" → (รอ 3 วินาที) → "text"

จุดเด่น

  • ใช้ Grand Central Dispatch (GCD) - ระบบจัดการ Thread ของ Apple
  • Syntax สะอาด ใช้ Closure/Trailing Closure
  • ระบุเวลาได้แม่นยำด้วย DispatchTime
  • รันบน Main Queue (เหมาะสำหรับ UI Updates)

วิธีที่ 2: Timer.scheduledTimer (Classic)

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        print("one")
        
        Timer.scheduledTimer(timeInterval: 3.0,
                            target: self,
                            selector: #selector(hello),
                            userInfo: nil,
                            repeats: false)
    }
    
    @objc func hello() {
        print("text")
    }
}

ความแตกต่าง

  • ใช้ Selector/Objective-C Runtime
  • ต้องมี @objc attribute
  • ยากกว่าในการ Cancel (ต้องเก็บ reference Timer ไว้)
  • เหมาะสำหรับ Repeating Timer (repeats: true)

วิธีที่ 3: Async/Await (Swift 5.5+ / iOS 15+)

func delayedCall() async {
    print("one")
    try? await Task.sleep(nanoseconds: 3_000_000_000) // 3 วินาที
    hello()
}

func hello() {
    print("text")
}

// เรียกใช้:
Task { await delayedCall() }

สรุป: ควรใช้วิธีไหน?

สถานการณ์แนะนำ
Delay ครั้งเดียว, UI UpdateDispatchQueue.asyncAfter
Repeating TaskTimer.scheduledTimer(repeats: true)
Async/Await Context (Swift 5.5+)Task.sleep
ต้อง Cancel ได้Timer (เก็บ reference) หรือ DispatchWorkItem

ตัวอย่าง Cancel ด้วย DispatchWorkItem

let workItem = DispatchWorkItem { hello() }
DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: workItem)

// ยกเลิกได้:
workItem.cancel()