Background Task: khái niệm chính, đăng ký tác vụ và thực thi trong nền

Tác giả: IT Sectr Đã đăng: 2026-03-27 Thời gian đọc: 10 phút

Background Task là một cơ chế iOS cho phép ứng dụng hoàn thành một thao tác sau khi chuyển sang chế độ nền. Hệ thống cấp thời gian giới hạn (lên đến 30 giây) để thực thi tác vụ, sau đó ứng dụng sẽ bị tạm dừng cưỡng bức. Theo Apple, 2026, việc sử dụng expiration handler là yêu cầu bắt buộc để hoàn thành tác vụ nền một cách chính xác.

Những điểm chính

  • Background Task — cơ chế iOS để hoàn thành thao tác sau khi ứng dụng vào nền.
  • beginBackgroundTask — phương thức chính của UIApplication để đăng ký tác vụ nền.
  • Expiration handler — khối mã được hệ thống gọi khi hết thời gian được cấp.
  • Giới hạn 30 giây — thời gian thực thi tiêu chuẩn, có thể kéo dài qua Background Modes.
  • UIApplication.shared.endBackgroundTask — lời gọi bắt buộc để hoàn thành tác vụ chính xác.

Background Task trong iOS là gì?

Background Task là cơ chế lập trình iOS cho phép ứng dụng kéo dài thời gian thực thi sau khi chuyển sang nền. Khi người dùng thu nhỏ ứng dụng, hệ thống gọi UIApplicationDelegate.applicationDidEnterBackground. Nếu có thao tác quan trọng đang được thực hiện tại thời điểm đó (lưu dữ liệu, gửi yêu cầu), ứng dụng có thể yêu cầu thêm thời gian qua beginBackgroundTask.

Tại sao cần Background Tasks

Nếu không sử dụng Background Task, ứng dụng sẽ bị tạm dừng cưỡng bức trong vòng 3–5 giây sau khi vào nền. Tất cả các thao tác chưa hoàn thành đều bị gián đoạn: dữ liệu không được lưu, yêu cầu mạng bị hủy bỏ, trạng thái bị mất. Background Task cấp cho ứng dụng tới 30 giây để hoàn thành các thao tác này một cách chính xác.

  • Lưu trạng thái — ghi dữ liệu vào CoreData, UserDefaults hoặc hệ thống tệp tin.
  • Hoàn thành yêu cầu mạng — chờ phản hồi từ máy chủ và xử lý kết quả.
  • Gửi phân tích — truyền sự kiện đến máy chủ phân tích trước khi tạm dừng.
  • Dọn dẹp tài nguyên — đóng bộ mô tả tệp, giải phóng bộ nhớ.
  • Lưu cache — ghi kết quả trung gian để khôi phục ở lần khởi chạy tiếp theo.

Lịch sử và sự phát triển

beginBackgroundTask xuất hiện trong iOS 4.0 — bản phát hành đầu tiên hỗ trợ đa nhiệm. Trước iOS 4, ứng dụng bị kết thúc hoàn toàn khi nhấn nút Home. iOS 7 giới thiệu Background Fetch và cấu hình nền URLSession. Bắt đầu từ iOS 13, Apple khuyến nghị BGTaskScheduler cho các dự án mới, nhưng beginBackgroundTask vẫn phù hợp cho các thao tác ngắn hạn.

Cách beginBackgroundTask hoạt động: vòng đời

beginBackgroundTask là phương thức UIApplication đăng ký một tác vụ và trả về UIBackgroundTaskIdentifier duy nhất. Hệ thống tăng bộ đếm thời gian thực thi nền. Khi hết thời gian, expiration handler được gọi, sau đó ứng dụng phải gọi endBackgroundTask(identifier:) để hoàn thành tác vụ chính xác.

Quy trình thực thi từng bước

Bước 1 — ứng dụng nhận thông báo didEnterBackground. Bước 2 — beginBackgroundTask(expirationHandler:) được gọi. Bước 3 — thao tác quan trọng (lưu, yêu cầu mạng) được thực hiện. Bước 4 — khi hoàn thành, endBackgroundTask(identifier:) được gọi. Nếu thao tác không hoàn thành trong 30 giây — hệ thống gọi expiration handler, và ứng dụng phải kết thúc tác vụ ngay lập tức.

swift
var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

func startBackgroundTask() {
    backgroundTaskID = UIApplication.shared.beginBackgroundTask {
        // Expiration handler
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
    }
}

func finishBackgroundTask() {
    UIApplication.shared.endBackgroundTask(backgroundTaskID)
    backgroundTaskID = .invalid
}

UIApplication.shared.backgroundTimeRemaining

Thuộc tính backgroundTimeRemaining trả về số giây còn lại trước khi tác vụ nền bị kết thúc cưỡng bức. Giá trị giảm dần theo thời gian thực. Nếu ứng dụng không ở chế độ nền — nó trả về DBL_MAX. Sử dụng thuộc tính này để điều chỉnh hành vi: khi còn dưới 5 giây, hãy ngắt các thao tác dài và lưu tiến trình.

Nhiều tác vụ

Một ứng dụng có thể đăng ký nhiều Background Tasks cùng lúc. Mỗi tác vụ nhận được mã định danh riêng. Tổng thời gian thực thi được cộng dồn — nếu 3 tác vụ được đăng ký, ứng dụng có thể nhận được tới 90 giây. Tuy nhiên, hệ thống có thể kết thúc ứng dụng sớm hơn nếu tài nguyên cạn kiệt hoặc vượt quá giới hạn pin.

Expiration handler: xử lý kết thúc bắt buộc

Expiration handler là khối mã mà hệ thống gọi khi hết thời gian được cấp cho tác vụ nền. Có expiration handler là yêu cầu bắt buộc của Apple. Nếu không có, ứng dụng có thể bị kết thúc cưỡng bức bởi hệ thống và dữ liệu có thể bị mất.

Những gì nên có trong expiration handler

Expiration handler phải thực hiện các hành động tối thiểu để lưu trạng thái ứng dụng: lưu dữ liệu hiện tại vào bộ nhớ liên tục, gọi endBackgroundTask với mã định danh tương ứng và đặt mã định danh thành .invalid. Bên trong expiration handler, không được phép bắt đầu các thao tác dài mới — thời gian thực thi bị giới hạn ở 1–2 giây.

swift
func handleExpiration() {
    // Đang lưu tiến trình thực thi
    saveProgressToUserDefaults()

    // Đang hủy các yêu cầu mạng đang hoạt động
    currentTask?.cancel()

    // Đang kết thúc Background Task
    UIApplication.shared.endBackgroundTask(backgroundTaskID)
    backgroundTaskID = .invalid
}

// Đăng ký với expiration handler
backgroundTaskID = UIApplication.shared.beginBackgroundTask(
    withName: "SaveDocument",
    expirationHandler: handleExpiration
)

Lỗi thường gặp với expiration handler

Lỗi phổ biến nhất là không gọi endBackgroundTask bên trong expiration handler. Trong trường hợp này, hệ thống tiếp tục coi tác vụ là đang hoạt động, ứng dụng không chuyển sang trạng thái Suspended và pin bị hao kiệt. Lỗi thứ hai là bắt đầu các thao tác dài bên trong expiration handler. Hệ thống có thể kết thúc ứng dụng trước khi chúng hoàn thành và dữ liệu sẽ bị mất.

Kiểm tra thời gian còn lại

Trong expiration handler, thời gian thực thi bị giới hạn nghiêm trọng — thường là dưới 1 giây. Do đó, bên trong handler bạn không thể thực hiện: tính toán phức tạp, yêu cầu mạng, ghi lượng lớn dữ liệu vào CoreData. Chỉ các thao tác nguyên tử: ghi một khóa vào UserDefaults, đặt cờ trạng thái, gọi endBackgroundTask.

Ví dụ mã Background Task trong Swift

Hãy xem xét một triển khai Background Task hoàn chỉnh để lưu tài liệu khi ứng dụng vào nền. Ví dụ bao gồm đăng ký tác vụ, thực hiện thao tác với kiểm tra thời gian còn lại và hoàn thành chính xác qua endBackgroundTask.

Lưu tài liệu với tiến trình

Khi vào nền, ứng dụng bắt đầu lưu một tài liệu lớn. Background Task cấp tới 30 giây cho thao tác. Nếu hết thời gian — expiration handler lưu kết quả trung gian. Sau khi lưu hoàn tất, endBackgroundTask được gọi để giải phóng tài nguyên.

swift
class DocumentManager {
    private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

    func saveDocumentInBackground(document: Document) {
        backgroundTaskID = UIApplication.shared.beginBackgroundTask {
            self.saveProgress(document)
            self.endBackgroundTask()
        }

        DispatchQueue.global().async {
            document.save()
            self.endBackgroundTask()
        }
    }

    private func endBackgroundTask() {
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
    }
}

Gửi dữ liệu lên máy chủ

Yêu cầu mạng trong nền đòi hỏi sự chú ý đặc biệt — expiration handler có thể ngắt yêu cầu trước khi nhận được phản hồi. Sử dụng URLSession với dataTask và kiểm tra backgroundTimeRemaining trước khi gửi. Nếu còn dưới 5 giây — hãy hoãn gửi cho đến lần đánh thức ứng dụng tiếp theo.

swift
func sendCriticalData(data: Data) {
    backgroundTaskID = UIApplication.shared.beginBackgroundTask {
        // Đang lưu dữ liệu để gửi lại
        saveForRetry(data)
        self.endBackgroundTask()
    }

    let task = URLSession.shared.dataTask(with: request) { _, _, error in
        if error != nil {
            saveForRetry(data)
        }
        self.endBackgroundTask()
    }
    task.resume()
}

Giám sát thời gian còn lại

Đối với các thao tác dài, hãy giám sát UIApplication.shared.backgroundTimeRemaining. Nếu giá trị giảm xuống dưới ngưỡng (10 giây), hãy ngắt thao tác hiện tại và bắt đầu lưu kết quả trung gian. Điều này cho phép hoàn thành chính xác trước khi expiration handler bị gọi cưỡng bức.

Các phương pháp hay nhất khi sử dụng Background Task

Background Task là cơ chế mạnh mẽ, nhưng sử dụng không đúng cách dẫn đến các vấn đề về pin và hiệu năng. Tuân theo các khuyến nghị của Apple và các phương pháp đã được cộng đồng kiểm chứng sẽ giúp tránh các lỗi phổ biến và đảm bảo hoạt động ổn định của ứng dụng.

Giảm thiểu thời gian thực thi

Hoàn thành Background Task càng nhanh càng tốt. Mỗi giây thực thi trong nền đều tiêu hao pin. Thời gian tối ưu — dưới 5 giây. Nếu thao tác mất nhiều thời gian hơn — hãy cân nhắc sử dụng BGTaskScheduler hoặc Background Modes. Đừng kéo dài tác vụ một cách giả tạo qua các lời gọi beginBackgroundTask mà không có nhu cầu thực sự.

Sử dụng đúng mã định danh

Lưu trữ UIBackgroundTaskIdentifier như một thuộc tính của lớp hoặc cấu trúc. Không bao giờ truyền nó như một biến toàn cục — điều này dẫn đến xung đột với nhiều tác vụ. Đặt mã định danh thành .invalid sau khi gọi endBackgroundTask để ngăn chặn kết thúc kép.

Kiểm thử Background Task

Trong Xcode Simulator, chuyển ứng dụng sang nền qua nút Home (Command + Shift + H). Sử dụng Debug — Simulate Background Fetch để kiểm thử đánh thức nền. Để mô phỏng hết thời gian, đặt Biến môi trường BACKGROUND_TASK_SIMULATE_EXPIRATION = YES — expiration handler sẽ được gọi trong vòng 5 giây.

swift
// Đang kiểm tra thời gian còn lại trước khi bắt đầu thao tác
let remaining = UIApplication.shared.backgroundTimeRemaining
guard remaining > 10.0 else {
    // Không đủ thời gian — hoãn tác vụ
    scheduleForNextLaunch()
    return
}

// Đang thực thi thao tác với kiểm soát thời gian
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
    saveProgress()
    self.endBackgroundTask()
}

Tránh vòng lặp retain

Expiration handler capture self — điều này có thể tạo vòng lặp retain nếu backgroundTaskID được lưu trữ như thuộc tính của cùng một đối tượng. Sử dụng [weak self] trong closure hoặc lưu trữ mã định danh riêng biệt. Vòng lặp retain dẫn đến rò rỉ bộ nhớ — đối tượng sẽ không được giải phóng cho đến khi ứng dụng kết thúc.

Background Task vs BGTaskScheduler: so sánh cách tiếp cận

Với bản phát hành iOS 13, Apple đã giới thiệu BGTaskScheduler — sự thay thế hiện đại cho API Background Task cũ. Cả hai cơ chế đều giải quyết các tác vụ tương tự, nhưng BGTaskScheduler cung cấp nhiều kiểm soát và linh hoạt hơn. Hiểu được sự khác biệt sẽ giúp chọn công cụ phù hợp cho một kịch bản cụ thể.

Đặc điểmBackground TaskBGTaskScheduler
Phiên bản iOS4.0+13.0+
Thời gian tối đa30 giây30 giây / 10 phút (processing)
Khởi tạodidEnterBackgroundLập lịch + hệ thống
Đảm bảo thực thiChỉ khi vào nềnBất kỳ lúc nào hệ thống thuận tiện
Expiration handlerCó, bắt buộcCó, qua task.expirationHandler
InternetYêu cầu khi khởi độngCó sẵn qua requiresNetworkConnectivity
SạcKhông yêu cầuTùy chọn cho processing

Khi nào sử dụng Background Task

beginBackgroundTask phù hợp cho các thao tác ngắn hạn cần được thực thi ngay lập tức khi vào nền: lưu trạng thái, hoàn thành yêu cầu mạng, lưu dữ liệu vào cache. API đơn giản và không yêu cầu cấu hình Info.plist hoặc đăng ký mã định danh. Lý tưởng cho các thao tác mất dưới 10 giây.

Khi nào sử dụng BGTaskScheduler

BGTaskScheduler phù hợp cho các tác vụ có thể được thực thi bất kỳ lúc nào thuận tiện: đồng bộ định kỳ, dọn dẹp cache, cập nhật widget. Hệ thống tự chọn thời điểm tối ưu dựa trên hành vi người dùng và trạng thái pin. Đối với các thao tác dài (lên đến 10 phút), hãy sử dụng BGProcessingTask.

Sử dụng kết hợp

Cả hai API có thể được sử dụng trong cùng một ứng dụng. Background Task — cho các thao tác tức thời khi vào nền (lưu bản nháp). BGTaskScheduler — cho các cập nhật theo lịch trình (đồng bộ mỗi 6 giờ). Phân chia trách nhiệm đảm bảo bảo toàn dữ liệu chính xác và bảo trì nền tiết kiệm năng lượng.

Câu hỏi thường gặp

Có thể gọi beginBackgroundTask bên ngoài didEnterBackground không?

Có, beginBackgroundTask có thể được gọi tại bất kỳ thời điểm nào trong quá trình thực thi ứng dụng. Tuy nhiên, việc cấp phát thời gian của hệ thống sẽ chỉ bắt đầu sau khi chuyển sang nền. Nếu ứng dụng ở tiền cảnh, gọi beginBackgroundTask không có hiệu lực — backgroundTimeRemaining trả về DBL_MAX và tác vụ sẽ được kích hoạt khi vào nền.

Điều gì xảy ra nếu không gọi endBackgroundTask?

Nếu endBackgroundTask không được gọi, hệ thống tiếp tục coi ứng dụng đang hoạt động trong nền. Sau 30 giây, expiration handler sẽ được gọi, nhưng nếu nó cũng thiếu endBackgroundTask — ứng dụng ở lại trong bộ nhớ, hao pin. Trong iOS 13+, hệ thống kết thúc cưỡng bức ứng dụng đó sau 3 phút.

Làm thế nào để kéo dài Background Task quá 30 giây?

Thời gian tiêu chuẩn là 30 giây. Chỉ có thể kéo dài qua Background Modes: Âm thanh (phát lại), Vị trí (định vị), Bluetooth (BLE). Hoặc qua BGProcessingTask (iOS 13+) — lên đến 10 phút với sạc và Wi-Fi. beginBackgroundTask tự nó không cung cấp cách để tăng giới hạn.

Background Task có hoạt động trên iPad không?

Có, iPadOS hỗ trợ đầy đủ beginBackgroundTask với các giới hạn tương tự như iOS. Trên iPad với Stage Manager, ứng dụng có thể ở lại bộ nhớ lâu hơn — hệ thống tạm dừng ứng dụng ít thường xuyên hơn do RAM lớn hơn. Nhưng giới hạn 30 giây cho tác vụ nền vẫn được giữ nguyên.

Làm thế nào để gỡ lỗi Background Task trên thiết bị thật?

Kết nối thiết bị với Xcode, khởi chạy ứng dụng, thu nhỏ nó — nhật ký hệ thống sẽ xuất hiện trong console. Sử dụng sysdiagnose để thu thập nhật ký chi tiết: kích hoạt cưỡng bức sysdiagnose từ thiết bị (Tăng âm lượng + Giảm âm lượng + Nguồn). Trong Xcode Debug Navigator, giám sát hoạt động của các tác vụ nền.

Tóm tắt

  • Background Task — cơ chế iOS để hoàn thành thao tác sau khi vào nền, có sẵn từ iOS 4.0.
  • beginBackgroundTask — phương thức UIApplication đăng ký tác vụ và trả về mã định danh để hoàn thành.
  • Expiration handler — khối mã bắt buộc được hệ thống gọi khi giới hạn 30 giây hết hạn.
  • endBackgroundTask — lời gọi bắt buộc để hoàn thành tác vụ chính xác; nếu không có, ứng dụng ở lại trong bộ nhớ.
  • BGTaskScheduler — giải pháp thay thế hiện đại (iOS 13+) với lập lịch, hai loại tác vụ và điều kiện thực thi.
  • backgroundTimeRemaining — thuộc tính để kiểm tra thời gian còn lại và điều chỉnh hành vi tác vụ.
  • Sử dụng Background Task cho các thao tác ngắn hạn tức thời và BGTaskScheduler cho các cập nhật nền theo lịch trình trong các dự án mới.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm