# Entrevista iOS Push Notifications 2026: APNs, tokens y troubleshooting > Guía completa para preparar entrevistas iOS sobre Push Notifications, APNs, gestión de tokens y troubleshooting. Preguntas frecuentes con respuestas detalladas. - Published: 2026-02-28 - Updated: 2026-04-29 - Author: SharpSkill - Tags: ios, push-notifications, apns, swift, interview - Reading time: 12 min --- Las Push Notifications siguen siendo un tema crítico en las entrevistas de iOS. Comprender cómo funciona APNs, gestionar device tokens y resolver problemas comunes demuestra un conocimiento profundo del ecosistema de Apple. Esta guía cubre las preguntas de entrevista más frecuentes. > **Punto clave de la entrevista** > > Los entrevistadores buscan candidatos que comprendan el ciclo de vida completo: desde el registro del dispositivo hasta la entrega de la notificación, incluyendo el manejo correcto de errores en cada etapa. ## Arquitectura APNs: la base de las notificaciones iOS Apple Push Notification service (APNs) es el servicio centralizado que gestiona la entrega de push notifications a los dispositivos Apple. Comprender su arquitectura resulta esencial para responder con eficacia a las preguntas de entrevista. ### ¿Cómo funciona APNs? El flujo de comunicación involucra a tres actores principales: la aplicación iOS, APNs y el servidor backend. Este es el proceso completo: ```swift // AppDelegate.swift import UIKit import UserNotifications @main class AppDelegate: UIResponder, UIApplicationDelegate { func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // Request notification authorization UNUserNotificationCenter.current().requestAuthorization( options: [.alert, .badge, .sound] ) { granted, error in guard granted else { return } // Register with APNs DispatchQueue.main.async { application.registerForRemoteNotifications() } } return true } } ``` El registro APNs ocurre en dos pasos: obtener la autorización del usuario y luego llamar a `registerForRemoteNotifications()`. ### Gestión del device token El device token es un identificador único generado por APNs para apuntar a un dispositivo concreto. Este token puede cambiar y debe enviarse al servidor backend en cada lanzamiento de la aplicación. ```swift // AppDelegate.swift extension AppDelegate { // Callback when APNs provides the token func application( _ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data ) { // Convert token to hexadecimal string let tokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined() print("Device Token: \(tokenString)") // Send to backend server sendTokenToServer(tokenString) } // Callback on registration failure func application( _ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error ) { print("Failed to register: \(error.localizedDescription)") } private func sendTokenToServer(_ token: String) { // Implement HTTP request to backend } } ``` El token llega como `Data` y debe convertirse en una cadena hexadecimal antes de enviarlo al servidor. ## Preguntas frecuentes de entrevista sobre APNs Las entrevistas iOS combinan habitualmente preguntas teóricas y prácticas sobre APNs. Aquí están las más comunes con respuestas detalladas. ### Pregunta 1: ¿Cuál es la diferencia entre APNs sandbox y producción? > **Entornos APNs** > > APNs cuenta con dos entornos distintos con endpoints diferentes. Los tokens generados en un entorno no funcionan en el otro. | Entorno | Endpoint | Uso | |---------|----------|-----| | Sandbox | api.sandbox.push.apple.com | Debug, TestFlight | | Producción | api.push.apple.com | App Store | ### Pregunta 2: ¿Cómo gestionar la expiración del token? Los device tokens pueden cambiar por varias razones: restauración del sistema, instalación en un nuevo dispositivo o renovación periódica por parte de APNs. El servidor debe manejar correctamente las respuestas de error de APNs. ```swift // NotificationService.swift enum APNsError: Int { case badDeviceToken = 400 case unregistered = 410 case payloadTooLarge = 413 case tooManyRequests = 429 case internalServerError = 500 var shouldRemoveToken: Bool { // Remove token only if device is no longer registered return self == .unregistered || self == .badDeviceToken } } struct APNsResponse { let statusCode: Int let deviceToken: String func handleError() { guard let error = APNsError(rawValue: statusCode) else { return } if error.shouldRemoveToken { // Remove token from database TokenRepository.shared.remove(deviceToken) } } } ``` El manejo de errores APNs en el servidor resulta crucial para mantener limpia la base de datos de tokens y evitar peticiones innecesarias. ### Pregunta 3: ¿Cómo implementar silent notifications? Las silent notifications permiten despertar la aplicación en segundo plano para realizar tareas sin mostrar ninguna alerta al usuario. ```swift // AppDelegate.swift func application( _ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void ) { // Check if this is a silent notification guard let aps = userInfo["aps"] as? [String: Any], aps["content-available"] as? Int == 1 else { completionHandler(.noData) return } // Perform background task performBackgroundTask { result in switch result { case .success: completionHandler(.newData) case .failure: completionHandler(.failed) } } } ``` El payload JSON de una silent notification debe contener `"content-available": 1` dentro del objeto `aps`. ## Notification Service Extension: personalización avanzada Las Notification Service Extensions permiten modificar el contenido de la notificación antes de mostrarla. Esta funcionalidad aparece a menudo en las entrevistas. ### Crear una Service Extension ```swift // NotificationService.swift (in Extension target) 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 bestAttemptContent = request.content.mutableCopy() as? UNMutableNotificationContent guard let bestAttemptContent = bestAttemptContent else { contentHandler(request.content) return } // Modify content if let imageURLString = bestAttemptContent.userInfo["image-url"] as? String, let imageURL = URL(string: imageURLString) { downloadImage(from: imageURL) { attachment in if let attachment = attachment { bestAttemptContent.attachments = [attachment] } contentHandler(bestAttemptContent) } } else { contentHandler(bestAttemptContent) } } override func serviceExtensionTimeWillExpire() { // Called when time limit (30 seconds) is exceeded if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } private func downloadImage( from url: URL, completion: @escaping (UNNotificationAttachment?) -> Void ) { URLSession.shared.downloadTask(with: url) { localURL, _, error in guard let localURL = localURL, error == nil else { completion(nil) return } let tempDirectory = FileManager.default.temporaryDirectory let fileName = url.lastPathComponent let destinationURL = tempDirectory.appendingPathComponent(fileName) try? FileManager.default.moveItem(at: localURL, to: destinationURL) let attachment = try? UNNotificationAttachment( identifier: fileName, url: destinationURL, options: nil ) completion(attachment) }.resume() } } ``` La extensión dispone de 30 segundos para modificar el contenido. El método `serviceExtensionTimeWillExpire()` se llama si se supera ese límite. ## Troubleshooting de Push Notifications La depuración de push notifications es un tema recurrente en entrevistas. Los candidatos deben conocer las herramientas y las técnicas de diagnóstico. ### Verificar el estado del registro ```swift // DebugHelper.swift struct PushNotificationDebugger { static func checkNotificationStatus() async { let center = UNUserNotificationCenter.current() let settings = await center.notificationSettings() print("=== Push Notification Status ===") print("Authorization: \(settings.authorizationStatus.description)") print("Alert: \(settings.alertSetting.description)") print("Badge: \(settings.badgeSetting.description)") print("Sound: \(settings.soundSetting.description)") print("Notification Center: \(settings.notificationCenterSetting.description)") } } extension UNAuthorizationStatus { var description: String { switch self { case .notDetermined: return "Not Determined" case .denied: return "Denied" case .authorized: return "Authorized" case .provisional: return "Provisional" case .ephemeral: return "Ephemeral" @unknown default: return "Unknown" } } } ``` Esta función de debug permite verificar rápidamente el estado de autorización de las notificaciones. ### Errores comunes y soluciones > **Errores frecuentes que conviene conocer** > > Los entrevistadores suelen preguntar por errores comunes y sus soluciones. Estos son los más importantes que conviene tener presentes. | Error | Causa | Solución | |-------|-------|----------| | Token inválido | Entorno incorrecto (sandbox/prod) | Verificar el provisioning profile | | Notificación no recibida | Modo bajo consumo activado | Probar con la batería cargada | | Extensión no llamada | Payload sin `mutable-content` | Añadir `"mutable-content": 1` | | Background fetch fallido | App cerrada por el usuario | Informar al usuario de la limitación | ### Probar APNs directamente Para probar las notificaciones durante el desarrollo, la herramienta `curl` permite enviar peticiones directamente a APNs: ```swift // TestPayload.swift struct APNsTestPayload { static let silentNotification = """ { "aps": { "content-available": 1 }, "custom-data": "test" } """ static let richNotification = """ { "aps": { "alert": { "title": "New message", "body": "Message content" }, "mutable-content": 1, "sound": "default" }, "image-url": "https://example.com/image.jpg" } """ } ``` Estos payloads de prueba resultan útiles para validar el comportamiento de la aplicación con distintos tipos de notificación. ## Buenas prácticas en producción Las preguntas sobre buenas prácticas ayudan a evaluar la experiencia del candidato con aplicaciones en producción. ### Manejo de errores de red ```swift // PushTokenManager.swift actor PushTokenManager { private var pendingToken: String? private var retryCount = 0 private let maxRetries = 3 func registerToken(_ token: String) async { pendingToken = token await sendTokenWithRetry() } private func sendTokenWithRetry() async { guard let token = pendingToken else { return } do { try await APIClient.shared.registerPushToken(token) pendingToken = nil retryCount = 0 } catch { retryCount += 1 if retryCount < maxRetries { // Retry with exponential backoff let delay = UInt64(pow(2.0, Double(retryCount))) * 1_000_000_000 try? await Task.sleep(nanoseconds: delay) await sendTokenWithRetry() } } } } ``` El uso de un `actor` garantiza la seguridad entre hilos a la hora de gestionar tokens en entornos concurrentes. ### Persistencia local del token ```swift // TokenStorage.swift struct TokenStorage { private static let tokenKey = "com.app.pushToken" static func save(_ token: String) { UserDefaults.standard.set(token, forKey: tokenKey) } static func retrieve() -> String? { UserDefaults.standard.string(forKey: tokenKey) } static func hasTokenChanged(_ newToken: String) -> Bool { guard let savedToken = retrieve() else { return true } return savedToken != newToken } } ``` Guardar el token en local evita llamadas de red innecesarias cuando el token no ha cambiado. ## Conclusión Dominar las iOS Push Notifications demuestra un conocimiento profundo del ecosistema de Apple y de las interacciones cliente-servidor. Puntos clave a recordar para las entrevistas: ✅ Arquitectura APNs: comprender el flujo completo desde el registro hasta la entrega ✅ Device tokens: ciclo de vida y gestión de los cambios de token ✅ Notification Service Extension: personalización del contenido con un límite de 30 segundos ✅ Troubleshooting: conocer los errores frecuentes y sus soluciones ✅ Silent notifications: `content-available` para el background fetch ✅ Buenas prácticas: lógica de reintento, persistencia local, manejo de errores --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/es/blog/ios/ios-push-notifications-apns-interview