Nếu muốn chạy timer khi app ở background, Apple cung cấp beginBackgroundTask(withExpirationHandler:). Tuy nhiên, thời gian tối đa chỉ khoảng 30 giây đến 3 phút (tùy iOS version và trạng thái thiết bị).
Ví dụ: In log mỗi giây khi app vào background
Bước 1: Tạo dự án
Xcode → Single View App → Tên: "BackgroundTimer".
Bước 2: Code trong AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var backgroundTaskIdentifier: UIBackgroundTaskIdentifier?
func applicationDidEnterBackground(_ application: UIApplication) {
// 1. Đăng ký background task
backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: {
// Handler khi hết thời gian background
UIApplication.shared.endBackgroundTask(self.backgroundTaskIdentifier!)
self.backgroundTaskIdentifier = .invalid
})
// 2. Tạo timer lặp lại mỗi 1 giây
Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(doSomething), userInfo: nil, repeats: true)
}
@objc func doSomething() {
print("Đang chạy background: \(Date())")
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Kết thúc background task khi app quay lại foreground
if let taskId = backgroundTaskIdentifier, taskId != .invalid {
UIApplication.shared.endBackgroundTask(taskId)
backgroundTaskIdentifier = .invalid
}
}
}
Giải thích quan trọng
| Khía cạnh | Chi tiết |
|---|---|
| Thời gian tối đa | ~30 giây - 3 phút (iOS quyết định, không kiểm soát được) |
| expirationHandler | Bắt buộc phải gọi endBackgroundTask ở đây, không thì app bị kill |
| Timer | Chỉ chạy được trong thời gian background task được cấp |
| Foreground | Timer tiếp tục chạy bình thường khi app active |
Các trường hợp dùng background task hợp lệ
- Hoàn tất upload/download file lớn
- Lưu dữ liệu quan trọng trước khi tắt
- Xử lý task ngắn (dưới 30s)
- VoIP, Music playback, Location updates (cần capability đặc biệt)
Không nên dùng cho
- Chạy timer vô thời hạn
- Thực hiện network request dài
- Xử lý logic phức tạp
Alternatives cho background execution dài hơn
- Background Fetch:
setMinimumBackgroundFetchInterval- iOS tự quyết định khi nào chạy - Background App Refresh: User bật trong Settings
- Silent Push Notification: Server push để đánh thức app
- Background Processing (iOS 13+):
BGProcessingTaskcho task nặng, cần điện nguồn + WiFi - Location Updates: Capability "Location updates" trong Background Modes
Test
- Chạy app trên thiết bị thật (simulator không chính xác)
- Nhấn Home / vuốt lên để đưa app vào background
- Xem console Xcode: "Đang chạy background..." in ra mỗi giây
- Sau ~30-180 giây: log dừng lại (expirationHandler được gọi)
- Mở app lại: timer tiếp tục in log

Lưu ý
Kể từ iOS 13, Apple khuyến nghị dùng Background Tasks Framework (BGAppRefreshTask, BGProcessingTask) thay vì beginBackgroundTask cho các tác vụ định kỳ.