Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> iOS

Cách gọi hàm sau một khoảng thời gian trễ (delay) trong Swift iOS

Giới thiệu

Trong phát triển iOS, thường cần thực thi một đoạn mã sau một khoảng thời gian trễ. Bài viết này giới thiệu 2 cách phổ biến: DispatchQueue.asyncAfter (khuyên dùng) và Timer.

Cách 1: DispatchQueue.asyncAfter (Khuyên dùng)

Sử dụng GCD (Grand Central Dispatch) - hiện đại, an toàn, dễ đọc.

Ví dụ trong Playground

func functionOne() {
    let delayTime = DispatchTime.now() + 3.0 // 3 giây
    print("Một")
    
    DispatchQueue.main.asyncAfter(deadline: delayTime) {
        hello()
    }
}

func hello() {
    print("Chào")
}

functionOne()
// Kết quả: "Một" in ra ngay, sau 3 giây in "Chào"

Trong dự án thực tế (ViewController)

override func viewDidLoad() {
    super.viewDidLoad()
    
    DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
        self.performDelayedAction()
    }
}

func performDelayedAction() {
    print("Thực thi sau 2 giây")
    // Cập nhật UI, gọi API, v.v.
}

Cách 2: Timer.scheduledTimer (Cách cũ)

Phù hợp khi cần lặp lại (repeating) hoặc cần hủy (invalidate) timer.

Ví dụ

class ViewController: UIViewController {
    var timer: Timer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        print("Một")
        
        timer = Timer.scheduledTimer(timeInterval: 3.0,
                                     target: self,
                                     selector: #selector(hello),
                                     userInfo: nil,
                                     repeats: false) // Chạy 1 lần
    }
    
    @objc func hello() {
        print("Chào")
    }
    
    deinit {
        timer?.invalidate() // Hủy timer khi view controller bị giải phóng
    }
}

So sánh hai cách

Đặc điểmDispatchQueue.asyncAfterTimer
Cú phápClosure-based, hiện đạiTarget-Action, Objective-C style
Hủy thực thiKhó (cần DispatchWorkItem)Dễ dàng với timer.invalidate()
Lặp lạiKhông hỗ trợ trực tiếpHỗ trợ repeats: true
Thread safetyTốt (chỉ định queue)Chạy trên RunLoop của thread tạo
PrecisionCao (nanosecond)Thấp hơn (millisecond)

Best Practice

  • Ưu tiên DispatchQueue.main.asyncAfter cho các tác vụ đơn giản, chạy một lần.
  • Dùng Timer khi cần lặp lại hoặc cần khả năng hủy giữa chừng.
  • Luôn dùng weak self trong closure để tránh retain cycle:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
    self?.updateUI()
}