Notification Extension là cơ chế iOS cho phép sửa đổi nội dung và giao diện của thông báo push trước khi hiển thị cho người dùng. Các tiện ích mở rộng hoạt động phía hệ điều hành trong một tiến trình riêng: UNNotificationServiceExtension xử lý nội dung đến, trong khi UNNotificationContentExtension quản lý giao diện. Theo Apple Developer Documentation, 2026, Service Extension có tối đa 30 giây để thực hiện tác vụ trước khi thông báo được hiển thị. Giới hạn này rất quan trọng khi tải tệp đính kèm hoặc giải mã dữ liệu.
Điểm chính
Notification Extension là một thành phần phần mềm iOS mở rộng hành vi tiêu chuẩn của thông báo push bằng cách thêm khả năng sửa đổi nội dung và tùy chỉnh giao diện. Không giống như thông báo thông thường được hệ thống hiển thị ở định dạng tiêu chuẩn, tiện ích mở rộng cho phép nhà phát triển tác động đến nội dung trước khi hiển thị và tạo giao diện người dùng độc đáo.
Apple cung cấp hai loại Notification Extension cho các mục đích khác nhau: UNNotificationServiceExtension xử lý tải trọng đến, trong khi UNNotificationContentExtension quản lý hiển thị. Service Extension chạy trước khi thông báo được hiển thị và có thời gian thực thi giới hạn — lên đến 30 giây theo Apple Developer Documentation. Content Extension được kích hoạt sau khi người dùng tương tác với thông báo và hiển thị chế độ xem tùy chỉnh.
Thông báo push iOS tiêu chuẩn được hệ thống tự động hiển thị dựa trên các trường alert, title và subtitle từ tải trọng JSON. Notification Extension chặn quyền điều khiển: Service Extension nhận tải trọng thô, sửa đổi nó và chuyển cho hệ thống để hiển thị. Content Extension thay thế biểu ngữ tiêu chuẩn bằng giao diện tùy chỉnh với bất kỳ thành phần điều khiển nào.
Khi thiết bị nhận được thông báo push với khóa mutable-content: 1, hệ thống khởi chạy Service Extension trong một tiến trình riêng. Tiến trình tiện ích mở rộng được cách ly khỏi ứng dụng chính và có hộp cát riêng với giới hạn bộ nhớ 50 MB. Sau khi hoàn tất xử lý, tiện ích mở rộng gọi completion handler, chuyển UNNotificationContent đã sửa đổi cho hệ thống để hiển thị.
UNNotificationServiceExtension là công cụ chính để sửa đổi thông báo push theo chương trình trước khi hiển thị cho người dùng. Tiện ích mở rộng tự động kích hoạt khi nhận được thông báo có tải trọng được đặt cờ mutable-content: 1. Trong vòng 30 giây, tiện ích mở rộng có thể tải tệp đính kèm đa phương tiện, thay đổi văn bản, giải mã dữ liệu đã mã hóa hoặc làm phong phú nội dung.
Tiện ích mở rộng triển khai hai phương thức chính từ giao thức UNNotificationServiceExtension. Phương thức didReceive nhận yêu cầu đến với UNNotificationRequest thô và cho phép sửa đổi thông qua completion handler với UNNotificationContent mới. Phương thức serviceExtensionTimeWillExpire được hệ thống gọi một giây trước khi hết thời gian chờ — trong đó bạn phải hoàn tất xử lý và chuyển kết quả hiện tại (có thể một phần).
Hãy xem xét tình huống máy chủ gửi push với URL hình ảnh trong trường tùy chỉnh. Service Extension tải hình ảnh này qua mạng, tạo UNNotificationAttachment và thêm vào nội dung. UNNotificationAttachment chấp nhận tệp hình ảnh, video hoặc âm thanh cục bộ và tự động sao chép vào hộp cát của tiện ích mở rộng. Sau khi tạo tệp đính kèm, tiện ích mở rộng chuyển nội dung đã cập nhật cho hệ thống.
class NotificationService: UNNotificationServiceExtension {
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler:
@escaping (UNNotificationContent) -> Void) {
let userInfo = request.content.userInfo
guard let imageURL = URL(string: userInfo["image-url"] as! String)
else { contentHandler(request.content); return }
let attachment = try! UNNotificationAttachment(
identifier: "image", url: imageURL,
options: [UNNotificationAttachmentOptionsTypeHintKey: "jpg"])
let modifiedContent = request.content.mutableCopy()
as! UNMutableNotificationContent
modifiedContent.attachments = [attachment]
contentHandler(modifiedContent)
}
override func serviceExtensionTimeWillExpire() {
contentHandler?(bestAttemptContent ?? request.content)
}
}
Khi thông báo có cùng tệp đính kèm được gửi thường xuyên, bạn nên lưu vào bộ nhớ đệm các tệp đã tải trên thiết bị. FileManager cung cấp quyền truy cập vào thư mục bộ nhớ đệm của tiện ích mở rộng, tồn tại giữa các lần khởi chạy. Điều này giảm thời gian xử lý cho các thông báo tiếp theo và giảm tải mạng. Theo Apple, lưu vào bộ nhớ đệm có thể giảm thời gian xử lý xuống còn 2–5 giây thay vì tải hoàn toàn.
UNNotificationContentExtension cho phép thay thế biểu ngữ thông báo tiêu chuẩn bằng giao diện tùy chỉnh được tạo trong Interface Builder hoặc SwiftUI. Tiện ích mở rộng được kích hoạt khi người dùng thực hiện hành động trên thông báo: chạm, vuốt xuống hoặc 3D Touch. Content Extension nhận nội dung đã được Service Extension xử lý và hiển thị trong chế độ xem tùy chỉnh.
Mỗi Content Extension được liên kết với một hoặc nhiều danh mục thông báo thông qua Info.plist. Danh mục được xác định trên máy chủ bằng trường category trong tải trọng APNS. Hệ thống tự động chọn tiện ích mở rộng phù hợp dựa trên danh mục của thông báo nhận được. Giao diện được xây dựng qua storyboard sử dụng các thành phần UIKit tiêu chuẩn hoặc SwiftUI View.
Content Extension hỗ trợ các nút tùy chỉnh và trình xử lý chạm được định nghĩa trong UNNotificationAction. UNNotificationAction được tạo ở giai đoạn đăng ký danh mục và có thể hỗ trợ nhập văn bản qua UNTextInputNotificationAction. Khi người dùng nhấn nút, tiện ích mở rộng nhận được callback didReceive với mã định danh hành động và có thể thực thi logic tương ứng — mở URL, gửi yêu cầu đến máy chủ hoặc cập nhật giao diện.
Content Extension chạy trong một tiến trình cách ly với vòng lặp thực thi riêng và giới hạn bộ nhớ khoảng 50 MB. Hiệu suất của tiện ích mở rộng rất quan trọng vì watchdog của hệ thống sẽ kết thúc tiến trình khi vượt quá giới hạn. Bạn nên tránh các tính toán nặng, tải hình ảnh lớn và yêu cầu mạng kéo dài bên trong Content Extension.
UNNotificationAttachment là một đối tượng thêm tệp đa phương tiện vào thông báo push: hình ảnh, video, âm thanh hoặc GIF. Tệp đính kèm được tạo từ URL tệp cục bộ phải nằm trong hộp cát của tiện ích mở rộng. Kích thước tối đa của tệp đính kèm không được vượt quá 10 MB, nếu không hệ thống sẽ từ chối tệp đính kèm khi tạo.
Apple hỗ trợ một tập hợp định dạng giới hạn cho tệp đính kèm đa phương tiện. Hình ảnh — JPEG, PNG, GIF (bao gồm hoạt hình), TIFF. Video — MPEG, MP4, MOV với thời lượng tối đa 30 giây. Âm thanh — MP3, AAC, WAV, CAF. Đối với mỗi định dạng, bạn có thể chỉ định loại qua UNNotificationAttachmentOptionsTypeHintKey, giúp hệ thống xử lý tệp chính xác.
Vì tải trọng push chỉ chứa URL, không phải tệp, việc tải tệp đính kèm phải được thực hiện bên trong Service Extension. Thời gian tải tối đa bị giới hạn ở 30 giây, do đó bạn nên sử dụng URLSession với cài đặt tối thiểu và vô hiệu hóa tải khi tín hiệu yếu. Nếu tệp đính kèm không được tải kịp, thông báo sẽ hiển thị mà không có phương tiện — đây là hành vi mặc định của hệ thống.
Hãy xem qua ví dụ Notification Extension hoàn chỉnh tải hình ảnh, lưu và thêm vào thông báo. NotificationService kế thừa từ UNNotificationServiceExtension và ghi đè phương thức didReceive. Ví dụ minh họa cách xử lý các trường tùy chọn, tạo tệp đính kèm và gọi completion handler với nội dung đã sửa đổi.
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler:
@escaping (UNNotificationContent) -> Void
) {
self.contentHandler = contentHandler
self.bestAttemptContent =
(request.content.mutableCopy()
as! UNMutableNotificationContent)
guard let attachmentURLString =
bestAttemptContent?.userInfo["attachment-url"] as? String,
let url = URL(string: attachmentURLString)
else {
contentHandler(request.content)
return
}
URLSession.shared.downloadTask(with: url) {
[weak self] localURL, _, error in
guard let localURL = localURL, error == nil
else {
contentHandler(request.content)
return
}
let attachment = try! UNNotificationAttachment(
identifier: "media", url: localURL)
self?.bestAttemptContent?.attachments = [attachment]
contentHandler(self?.bestAttemptContent
?? request.content)
}.resume()
}
override func serviceExtensionTimeWillExpire() {
if let content = bestAttemptContent {
contentHandler?(content)
}
}
}
Để tiện ích mở rộng hoạt động chính xác, cần đăng ký các danh mục thông báo trong Info.plist. Khóa NSExtensionPointIdentifier được đặt thành com.apple.usernotifications.service cho Service Extension hoặc com.apple.usernotifications.content cho Content Extension. Các danh mục được xác định trong AppDelegate khi khởi chạy ứng dụng qua UNUserNotificationCenter, và tiện ích mở rộng chỉ kích hoạt cho thông báo có danh mục phù hợp trong tải trọng.
Câu hỏi thường gặp
Service Extension sửa đổi nội dung trước khi thông báo được hiển thị — thêm phương tiện, thay đổi văn bản, giải mã dữ liệu. Content Extension thay thế giao diện thông báo bằng giao diện tùy chỉnh sau khi người dùng tương tác. Service Extension hoạt động trước khi hiển thị, Content Extension hoạt động sau đó.
Hệ thống phân bổ 30 giây để thực thi mã trong didReceive. Nếu xử lý không hoàn tất trong thời gian này, serviceExtensionTimeWillExpire được gọi, nơi bạn phải chuyển kết quả hiện tại. Bạn nên giới hạn trong 10–15 giây có tính đến việc tải tệp đính kèm.
Có, SwiftUI được hỗ trợ trong Content Extension từ iOS 16 trở lên. View được bọc trong UIHostingController và thêm vào storyboard. Tuy nhiên, do giới hạn bộ nhớ, bạn chỉ nên sử dụng SwiftUI cho các giao diện đơn giản với số lượng phần tử tối thiểu.
Trong trường hợp lỗi tải hoặc hết thời gian, chỉ cần gọi completion handler với nội dung gốc không có tệp đính kèm. Hệ thống sẽ hiển thị thông báo ở dạng tiêu chuẩn không có phương tiện. Ghi lại lỗi qua OSLog để chẩn đoán, nhưng không chặn hiển thị thông báo.
Tiện ích mở rộng chạy trong một tiến trình cách ly với giới hạn khoảng 50 MB. Khi vượt quá, hệ thống sẽ kết thúc tiến trình qua watchdog. Tránh tải tệp lớn, lưu trữ hình ảnh trong bộ nhớ và rò rỉ khi làm việc với URLSession.
Tổng kết
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.
Đọc thêm