# Seguimiento de la entrega de mensajes en iOS

Existe un [método de API](/es/developer/api-reference/device-api#messagedeliveryevent) en Pushwoosh que rastrea la entrega de notificaciones push. Las aplicaciones de iOS no son compatibles con este método de forma nativa, porque las notificaciones push en iOS son manejadas por el SO, no por el SDK de Pushwoosh. Puedes agregar el seguimiento de entrega agregando una Extensión de Servicio de Notificación a tu proyecto. Esta página muestra cómo implementar el seguimiento de entrega de mensajes para aplicaciones de iOS.

<Aside>
Requiere el SDK de Pushwoosh para iOS 7.x, que es compatible con iOS 13.0 y versiones posteriores.
</Aside>

<Aside type="note">
Desde el SDK de Pushwoosh para iOS 7.1.0, la integración recomendada es la clase base `PushwooshNotificationServiceExtension` que se muestra a continuación. Envía el evento de entrega de mensajes, establece el contador, descarga el archivo adjunto multimedia y maneja el fallback obligatorio `serviceExtensionTimeWillExpire` por ti. La API anterior `PWNotificationExtensionManager` todavía funciona, pero está obsoleta — consulta [Integración heredada](#legacy-integration).
</Aside>

## Agregar la Extensión de Servicio de Notificación

1. En Xcode, selecciona **File** > **New** > **Target...**

2. Selecciona **Notification Service Extension** y presiona **Next.**

<img src="/ios-push-notifications-ios-message-delivery-tracking-1.webp" alt="Selector de plantillas de destino de Xcode con la Extensión de Servicio de Notificación seleccionada"/>

3. Ingresa el nombre del producto y presiona **Finish.**

<Aside type="caution">
No selecciones **Activate** en el cuadro de diálogo que se muestra después de presionar **Finish**.
</Aside>

4. Presiona **Cancel** en el aviso **Activate scheme**.

<img
  src="/ios-push-notifications-ios-message-delivery-tracking-2.webp"
  alt="Aviso de Activate scheme con Cancel resaltado"
  style={{ display: "block", margin: "0 auto", maxWidth: "40%", height: "auto" }}
  width="400"
/>

Al cancelar, mantienes a Xcode depurando tu aplicación en lugar de la extensión que acabas de crear. Si la activaste por accidente, puedes volver a depurar tu aplicación dentro de Xcode.

## Dependencias para la Extensión de Servicio de Notificación (solo CocoaPods)

Si usas Swift Package Manager para gestionar las dependencias, puedes omitir este paso, ya que las dependencias se agregan automáticamente.

Abre tu `Podfile` y agrega la dependencia para el destino:

```ruby title="Podfile"
target 'NotificationServiceExtension' do
  use_frameworks!
  pod 'PushwooshXCFramework'
end
```

Ejecuta los siguientes comandos en la terminal para instalar las dependencias:

```shell
rm -rf Podfile.lock
pod deintegrate
pod setup
pod repo update
pod install
```

## Agregar código para el seguimiento de eventos de entrega de mensajes

Haz que tu extensión sea una subclase de `PushwooshNotificationServiceExtension`. Una subclase vacía es suficiente: Pushwoosh envía el evento de entrega de mensajes, establece el contador, descarga el archivo adjunto multimedia y maneja el fallback de tiempo de espera automáticamente.

Reemplaza el contenido generado de tu archivo **NotificationService**:

<Tabs>
<TabItem label="Swift">

```swift
import UserNotifications
import PushwooshFramework

class NotificationService: PushwooshNotificationServiceExtension {}
```

</TabItem>

<TabItem label="Objective-C">

```objective-c
#import <PushwooshFramework/PushwooshNotificationServiceExtension.h>

@interface NotificationService : PushwooshNotificationServiceExtension

@end

@implementation NotificationService

@end
```

</TabItem>
</Tabs>

<Aside type="tip">
Si no necesitas ningún código personalizado, puedes omitir el archivo fuente por completo y apuntar directamente la `NSExtensionPrincipalClass` del Info.plist de la extensión a `PushwooshNotificationServiceExtension`.
</Aside>

### ID de la aplicación

Desde la versión 7.1.0, la extensión hereda `Pushwoosh_APPID` (y otras claves `Pushwoosh_*`) del Info.plist de la aplicación anfitriona, por lo que ya no necesitas duplicarlo en la extensión. Agrega `Pushwoosh_APPID` al Info.plist de la extensión solo cuando quieras anular el valor del anfitrión:

```xml title="NotificationService/Info.plist"
<key>Pushwoosh_APPID</key>
<string>XXXXX-XXXXX</string>
```

<Aside type="note">
En versiones del SDK de Pushwoosh para iOS anteriores a la 7.1.0, la extensión no hereda la configuración de la aplicación anfitriona. En esas versiones, debes agregar `Pushwoosh_APPID` al Info.plist de la extensión.
</Aside>

### Grupo de aplicaciones (contador y proxy inverso)

Se necesita un Grupo de aplicaciones (App Group) compartido entre la aplicación y la extensión para sincronizar el contador del ícono y para leer la configuración del proxy inverso que almacena la aplicación anfitriona.

1. Agrega la capacidad **App Groups** al destino de la extensión y habilita el mismo grupo que en la aplicación anfitriona. Esto es obligatorio — sin el contenedor compartido, el contador del ícono y la configuración del proxy inverso no se pueden sincronizar.

2. Proporciona el nombre del Grupo de aplicaciones. Al igual que `Pushwoosh_APPID`, la extensión hereda `PW_APP_GROUPS_NAME` del Info.plist de la aplicación anfitriona desde la versión 7.1.0, por lo que si ya lo configuraste allí para los contadores, no necesitas agregarlo a la extensión. Configúralo en el Info.plist de la extensión solo para anular el valor del anfitrión, o proporciónalo programáticamente anulando `pushwooshAppGroupsName`.

```xml title="App Info.plist"
<key>PW_APP_GROUPS_NAME</key>
<string>group.com.example.app</string>
```

<Aside type="caution">
Si la aplicación anfitriona utiliza un proxy inverso (`Pushwoosh_ALLOW_REVERSE_PROXY`), la extensión necesita este Grupo de aplicaciones para leer la URL del proxy que la aplicación almacenó allí. Sin él, el evento de entrega se retiene en lugar de enviarse directamente, omitiendo el proxy.
</Aside>

## Personalizar la notificación (opcional)

La clase base expone algunos puntos de anulación, de menor a mayor control. Pushwoosh sigue ejecutando el evento de entrega, el contador, el archivo adjunto y el fallback de tiempo de espera en todos los casos.

Establece el Grupo de aplicaciones programáticamente en lugar de usar la clave del Info.plist:

```swift
override func pushwooshAppGroupsName() -> String? {
    "group.com.example.app"
}
```

Ejecuta una preparación asíncrona antes de que Pushwoosh procese el push — por ejemplo, precargando medios de Push Stories — sin anular el `didReceive` estándar. Llama a `completion` exactamente una vez, en el hilo principal:

```swift
override func pushwooshPrepare(for request: UNNotificationRequest,
                              completion: @escaping () -> Void) {
    // async work here
    completion()
}
```

Modifica el contenido antes de que se muestre anulando `didReceive`. Llama a `super` con tu propio manejador de contenido, muta el contenido dentro de él y luego reenvíalo al manejador original:

```swift
override func didReceive(_ request: UNNotificationRequest,
                         withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    super.didReceive(request) { content in
        let mutable = (content.mutableCopy() as? UNMutableNotificationContent) ?? content
        // customize `mutable` here
        contentHandler(mutable)
    }
}
```

## Integración heredada

<Aside type="caution">
`PWNotificationExtensionManager` está obsoleto desde la versión 7.1.0. Úsalo solo si no puedes subclasificar `PushwooshNotificationServiceExtension` — por ejemplo, una extensión que ya extiende la clase base de otro SDK, o un wrapper multiplataforma (React Native, Flutter, Unity). Las nuevas integraciones deben usar la clase base anterior.
</Aside>

Esta API de bajo nivel impulsa el mismo procesamiento (evento de entrega, contador, archivo adjunto) desde una `UNNotificationServiceExtension` simple:

<Tabs>
<TabItem label="Swift">

```swift
import UserNotifications
import PushwooshFramework

class NotificationService: UNNotificationServiceExtension {

    override func didReceive(_ request: UNNotificationRequest,
                             withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        PWNotificationExtensionManager.sharedManager()
            .handleNotificationRequest(request, contentHandler: contentHandler)
    }
}
```

</TabItem>

<TabItem label="Objective-C">

```objective-c
#import "PWNotificationExtensionManager.h"

@interface NotificationService : UNNotificationServiceExtension

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request
                   withContentHandler:(void (^)(UNNotificationContent *))contentHandler {
    [[PWNotificationExtensionManager sharedManager] handleNotificationRequest:request
                                                              contentHandler:contentHandler];
}

@end
```

</TabItem>
</Tabs>

## Comparte tus comentarios con nosotros

Tus comentarios nos ayudan a crear una mejor experiencia, por lo que nos encantaría saber de ti si tienes algún problema durante el proceso de integración del SDK. Si encuentras alguna dificultad, no dudes en compartir tus pensamientos con nosotros [a través de este formulario](https://docs.google.com/forms/d/e/1FAIpQLSd_0b8jwn-V_JmoPLIxIFYbHACCQhrzidOZV3ELywoQPXRSxw/viewform).