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

Cách thực thi tác vụ lặp lại theo khoảng thời gian cố định trong iOS (Timer)

Apple cung cấp class Timer để thực thi tác vụ sau một khoảng thời gian nhất định, gửi message đến target object.

Tài liệu Timer chính thức

Ví dụ: In "hello" mỗi 5 giây

Bước 1: Tạo dự án

Xcode → Single View App → Tên: "HelloTutorialsPoint".

Bước 2: Tạo phương thức timer

Mở ViewController.swift, thêm method doSomething() dưới viewDidLoad:

private func doSomething() {
    let timer = Timer.scheduledTimer(timeInterval: 5.0, 
                                     target: self, 
                                     selector: #selector(ViewController.hello), 
                                     userInfo: nil, 
                                     repeats: true)
}

Bước 3: Implement selector method

@objc func hello() {
    print("hello")
}

Bước 4: Gọi trong viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()
    self.doSomething()
}

Mã hoàn chỉnh

import UIKit

class ViewController: UIViewController {
    
    var timer: Timer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        startTimer()
    }
    
    func startTimer() {
        // Hủy timer cũ nếu có
        timer?.invalidate()
        
        // Tạo timer mới
        timer = Timer.scheduledTimer(timeInterval: 5.0, 
                                     target: self, 
                                     selector: #selector(hello), 
                                     userInfo: nil, 
                                     repeats: true)
    }
    
    @objc func hello() {
        print("hello - \(Date())")
    }
    
    // Quan trọng: Hủy timer khi view controller bị hủy
    deinit {
        timer?.invalidate()
        timer = nil
    }
}

Kết quả

Console in ra "hello" mỗi 5 giây.

Cách thực thi tác vụ lặp lại theo khoảng thời gian cố định trong iOS (Timer)

Các lưu ý quan trọng về Timer

Vấn đề Giải pháp
Retain cycle (memory leak) Timer retain target (self). Dùng weak self trong closure-based timer hoặc invalidate trong deinit
Timer không chính xác Timer không phải real-time, có độ trễ vài ms. Không dùng cho timing chính xác
Background Timer bị tạm dừng khi app vào background (trừ khi có background task)
RunLoop Timer gắn vào RunLoop.current. Nên chỉ định mode: .common cho UI responsive

Cách hiện đại hơn: Closure-based Timer (iOS 10+)

timer = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { [weak self] _ in
    self?.hello()
}
  • Không cần @objc và selector
  • Dễ dàng capture [weak self] tránh retain cycle
  • Code gọn gàng, Swifty hơn

DispatchSourceTimer (Hiệu năng cao, chính xác hơn)

let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
timer.schedule(deadline: .now(), repeating: 5.0)
timer.setEventHandler { [weak self] in
    self?.hello()
}
timer.resume()

// Hủy: timer.cancel()
  • Chạy trên background queue, không block main thread
  • Độ chính xác cao hơn Timer truyền thống
  • Phù hợp cho tác vụ nền, không cập nhật UI trực tiếp

Tóm tắt khi nào dùng cái nào

  • Timer.scheduledTimer: Đơn giản, cập nhật UI, tác vụ nhẹ
  • Closure-based Timer: Ưu tiên cho code Swift hiện đại
  • DispatchSourceTimer: Background task, độ chính xác cao, high frequency
  • CADisplayLink: Đồng bộ với refresh rate màn hình (60fps/120fps) - cho animation