# iOS App Clips

Los App Clips permiten a los usuarios completar una tarea rápidamente sin descargar la aplicación completa. Con Pushwoosh, puede enviar notificaciones push a los usuarios de App Clips: iOS otorga automáticamente **acceso a notificaciones por 8 horas** cuando se abre el App Clip.

## Requisitos

- SDK de Pushwoosh para iOS **7.0.33+**
- Xcode 15+
- Una **aplicación de Pushwoosh separada** para su App Clip (diferente bundle ID = aplicación separada)
- Un dispositivo real para pruebas (los tokens push no funcionan en el simulador)

## 1. Crear una aplicación en Pushwoosh

Su App Clip tiene un bundle ID diferente (por ejemplo, `com.yourapp.Clip`), por lo que necesita una **aplicación de Pushwoosh separada** con su propia clave APNs.

1. Vaya al [Panel de Control de Pushwoosh](https://app.pushwoosh.com/)
2. Cree una nueva aplicación con el bundle ID del App Clip
3. Suba su clave de autenticación APNs
4. Copie el **Application Code** y el **API Token**

## 2. Crear un target de App Clip

1. En Xcode: **File → New → Target → App Clip**
2. Agregue la capacidad **Push Notifications** al target del App Clip

Para ver capturas de pantalla detalladas sobre cómo agregar capacidades, consulte la [guía de integración básica](/es/developer/pushwoosh-sdk/ios-sdk/setting-up-pushwoosh-ios-sdk-7-0/basic-integration-guide/).

## 3. Agregar los frameworks de Pushwoosh

En la sección **Build Phases → Link Binary With Libraries** del target del App Clip, agregue:

- `PushwooshFramework.framework`
- `PushwooshCore.framework`
- `PushwooshBridge.framework`

## 4. Configurar Info.plist

```xml
<!-- Pushwoosh -->
<key>Pushwoosh_APPID</key>
<string>XXXXX-XXXXX</string>
<key>Pushwoosh_API_TOKEN</key>
<string>YOUR_API_TOKEN</string>

<!-- Ephemeral push (8-hour auto-grant, no dialog) -->
<key>NSAppClip</key>
<dict>
    <key>NSAppClipRequestEphemeralUserNotification</key>
    <true/>
    <key>NSAppClipRequestLocationConfirmation</key>
    <false/>
</dict>

<key>UIBackgroundModes</key>
<array>
    <string>remote-notification</string>
</array>
```

## 5. Inicializar el SDK

<Tabs>
<TabItem label="SwiftUI">
```swift
import SwiftUI
import PushwooshFramework

class AppClipDelegate: NSObject, UIApplicationDelegate, PWMessagingDelegate {

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
        Pushwoosh.configure.delegate = self
        Pushwoosh.configure.registerForPushNotifications()
        return true
    }

    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Pushwoosh.configure.handlePushRegistration(deviceToken)
    }

    func application(_ application: UIApplication,
                     didFailToRegisterForRemoteNotificationsWithError error: Error) {
        Pushwoosh.configure.handlePushRegistrationFailure(error as NSError)
    }

    func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        Pushwoosh.configure.handlePushReceived(userInfo)
        completionHandler(.noData)
    }

    func pushwoosh(_ pushwoosh: Pushwoosh, onMessageOpened message: PWMessage) {
        print("Push opened: \(message.payload ?? [:])")
    }
}

@main
struct YourAppClip: App {
    @UIApplicationDelegateAdaptor(AppClipDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
```
</TabItem>
<TabItem label="UIKit">
```swift
import UIKit
import PushwooshFramework

@main
class AppDelegate: UIResponder, UIApplicationDelegate, PWMessagingDelegate {

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        Pushwoosh.configure.delegate = self
        Pushwoosh.configure.registerForPushNotifications()
        return true
    }

    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Pushwoosh.configure.handlePushRegistration(deviceToken)
    }

    func application(_ application: UIApplication,
                     didFailToRegisterForRemoteNotificationsWithError error: Error) {
        Pushwoosh.configure.handlePushRegistrationFailure(error as NSError)
    }

    func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        Pushwoosh.configure.handlePushReceived(userInfo)
        completionHandler(.noData)
    }

    func pushwoosh(_ pushwoosh: Pushwoosh, onMessageOpened message: PWMessage) {
        print("Push opened: \(message.payload ?? [:])")
    }
}
```
</TabItem>
</Tabs>

Con los permisos efímeros, iOS otorga acceso push durante 8 horas automáticamente. Si desea usar el modo efímero **sin mostrar un cuadro de diálogo de permisos**, llame a `UIApplication.shared.registerForRemoteNotifications()` directamente en lugar de `Pushwoosh.configure.registerForPushNotifications()`.

Para solicitar permisos push **permanentes** (cuadro de diálogo estándar), use `Pushwoosh.configure.registerForPushNotifications()` como se muestra arriba.

## Permisos push efímeros

Cuando un usuario abre su App Clip, iOS otorga acceso a las notificaciones push durante **8 horas** sin preguntar. Después de 8 horas, el permiso expira. El usuario debe volver a abrir el App Clip para obtener otras 8 horas.

Para obtener un token push por 8 horas **sin mostrar un cuadro de diálogo de permisos**:

```swift
UIApplication.shared.registerForRemoteNotifications()
```

Para obtener un token push **permanente** (muestra el cuadro de diálogo de permisos estándar):

```swift
Pushwoosh.configure.registerForPushNotifications()
```

## Limitaciones

| Limitación | Detalles |
|---|---|
| **Sin notificaciones enriquecidas** | Los App Clips no pueden incluir Notification Service Extension: sin imágenes, sin notificaciones de comunicación |
| **Límite de tamaño** | 15 MB (iOS 16) / 50 MB (iOS 17+) |
| **Ventana push de 8 horas** | El permiso efímero expira después de 8 horas |
| **Sin procesamiento en segundo plano** | El push silencioso tiene funcionalidad limitada |
| **Device ID** | `identifierForVendor` devuelve ceros: el SDK maneja esto automáticamente (7.0.33+) |

## Cómo se ve

<center>

<img src="/ios-appclip-push.png" alt="Notificación push de App Clip en iPhone" width="300" />

*Notificación push recibida en un App Clip con permisos efímeros*

</center>