# Фрагменты приложений для iOS (App Clips)

Фрагменты приложений (App Clips) позволяют пользователям быстро выполнять задачи, не загружая полное приложение. С помощью Pushwoosh вы можете отправлять push-уведомления пользователям Фрагментов приложений — iOS автоматически предоставляет **8-часовой доступ к уведомлениям** при открытии Фрагмента приложения.


## Что вам понадобится

- Pushwoosh iOS SDK **7.0.33+**
- Xcode 15+
- **Отдельное приложение Pushwoosh** для вашего Фрагмента приложения (другой bundle ID = отдельное приложение)
- Реальное устройство для тестирования (push-токены не работают в симуляторе)

## 1. Создайте приложение в Pushwoosh

Ваш Фрагмент приложения имеет другой bundle ID (например, `com.yourapp.Clip`), поэтому ему требуется **отдельное приложение Pushwoosh** с собственным ключом APNs.

1. Перейдите в [панель управления Pushwoosh](https://app.pushwoosh.com/)
2. Создайте новое приложение с bundle ID Фрагмента приложения
3. Загрузите ваш ключ аутентификации APNs
4. Скопируйте **Application Code** и **API Token**



## 2. Создайте таргет App Clip

1. В Xcode: **File → New → Target → App Clip**
2. Добавьте возможность **Push Notifications** в таргет App Clip

Подробные скриншоты по добавлению возможностей см. в [руководстве по базовой интеграции](/ru/developer/pushwoosh-sdk/ios-sdk/setting-up-pushwoosh-ios-sdk-7-0/basic-integration-guide/).


## 3. Добавьте фреймворки Pushwoosh

В таргете App Clip, в разделе **Build Phases → Link Binary With Libraries**, добавьте:

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


## 4. Настройте Info.plist

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

<!-- Временный push (8-часовое авто-разрешение, без диалогового окна) -->
<key>NSAppClip</key>
<dict>
    <key>NSAppClipRequestEphemeralUserNotification</key>
    <true/>
    <key>NSAppClipRequestLocationConfirmation</key>
    <false/>
</dict>

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



## 5. Инициализируйте 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>

При использовании временных разрешений iOS автоматически предоставляет доступ к push-уведомлениям на 8 часов. Если вы хотите использовать временный режим **без отображения диалогового окна запроса разрешений**, вызовите `UIApplication.shared.registerForRemoteNotifications()` напрямую вместо `Pushwoosh.configure.registerForPushNotifications()`.

Чтобы запросить **постоянное** разрешение на push-уведомления (стандартное диалоговое окно), используйте `Pushwoosh.configure.registerForPushNotifications()`, как показано выше.



## Временные разрешения на push-уведомления

Когда пользователь открывает ваш Фрагмент приложения, iOS предоставляет доступ к push-уведомлениям на **8 часов** без запроса. Через 8 часов разрешение истекает. Пользователь должен снова открыть Фрагмент приложения, чтобы получить еще 8 часов.

Чтобы получить push-токен на 8 часов **без отображения диалогового окна запроса разрешений**:

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

Чтобы получить **постоянный** push-токен (отображает стандартное диалоговое окно запроса разрешений):

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

## Ограничения

| Ограничение | Детали |
|---|---|
| **Нет rich-уведомлений** | Фрагменты приложений не могут включать Notification Service Extension — нет изображений, нет Communication Notifications |
| **Ограничение по размеру** | 15 МБ (iOS 16) / 50 МБ (iOS 17+) |
| **8-часовое окно для push-уведомлений** | Временное разрешение истекает через 8 часов |
| **Нет фоновой обработки** | Silent push (тихие push-уведомления) имеют ограниченную функциональность |
| **Device ID** | `identifierForVendor` возвращает нули — SDK обрабатывает это автоматически (7.0.33+) |



## Как это выглядит

<center>

<img src="/ios-appclip-push.png" alt="Push-уведомление от Фрагмента приложения на iPhone" width="300" />

*Push-уведомление, полученное во Фрагменте приложения с временными разрешениями*

</center>