# Live Activities для iOS

<Aside type="tip">
Посмотрите видео о Live Activities для iOS
<YouTube id="jRrDh_pIZCE" playlabel="Видео на YouTube: Live Activities для iOS" /> 
</Aside>


[Live Activities](https://developer.apple.com/design/human-interface-guidelines/live-activities) отображают самые актуальные данные вашего приложения на экране блокировки iPhone или iPad и в Dynamic Island. Эта функция позволяет пользователям видеть актуальную информацию в реальном времени и выполнять быстрые действия, связанные с отображаемой информацией.

Вот несколько примеров использования Live Activities:

*   Показывать статус заказа в приложении доставки;
*   Предоставлять обратный отсчет в реальном времени в приложении для тренировок;
*   Показывать информацию об отслеживании в приложении такси;
*   Отображать статистику игры и текущий счет в спортивном приложении;
*   Предоставлять почасовые прогнозы в погодном приложении.

Вы можете включить Live Activities с помощью Pushwoosh iOS SDK, как описано ниже. Для управления Live Activities и обновления их контента используйте метод [/updateLiveActivity](/ru/developer/api-reference/ios-live-activities-api#updateliveactivity).



## Настройка 
<Aside type="caution" title="Важно" >
Live Activities в Pushwoosh поддерживают только [конфигурацию на основе токенов](/ru/developer/first-steps/connect-messaging-services/ios-configuration/ios-token-based-configuration/). [Конфигурация на основе сертификатов](/ru/developer/first-steps/connect-messaging-services/ios-configuration/ios-platform-configuration/) не поддерживается.
</Aside> 

### Добавьте расширение для виджета

1.  Создайте новый target

Перейдите в **File > New > Target** и выберите **Widget Extension**.

<img src="/ios-push-notifications-ios-live-activities-1.webp" alt=""/>

2.  Конфигурация Widget Extension
Введите имя, убедитесь, что выбрали **Include Live Activity**, и нажмите **Finish**.

<img src="/ios-push-notifications-ios-live-activities-2.webp" alt=""/>

###  Конфигурация Info.plist
Найдите файл Info.plist в основном target, вставьте ключ "Supports Live Activities" и установите его значение в YES.

```xml
	<key>NSSupportsLiveActivities</key>
	<true/>
```

<Aside type="tip" title="Частые обновления">
Если ваши Live Activities обновляются часто (например, результаты спортивных матчей в реальном времени), также добавьте `NSSupportsLiveActivitiesFrequentUpdates` со значением `true`. Apple ограничивает количество высокоприоритетных push-обновлений, которые приложение может отправлять в час. Этот ключ увеличивает этот лимит. См. параметр `apns_priority` в [справочнике по API Live Activities](/ru/developer/api-reference/ios-live-activities-api/#time-sensitive-push-and-delivery-priority) для получения информации о том, как управляется приоритет доставки для каждого обновления.

```xml
	<key>NSSupportsLiveActivitiesFrequentUpdates</key>
	<true/>
```
</Aside>

###  Включение Live Activities из приложения
Чтобы включить Live Activities, добавьте их код в существующее расширение виджета или создайте новое, если в вашем приложении его еще нет. Live Activities используют функциональность [SwiftUI](https://developer.apple.com/documentation/SwiftUI) и [WidgetKit](https://developer.apple.com/documentation/WidgetKit) для своего пользовательского интерфейса. ActivityKit управляет жизненным циклом каждого Live Activity: его API используется для запроса, обновления и завершения Live Activity, а также для получения push-уведомлений ActivityKit. Вы можете узнать больше о Live Activities в [документации Apple](https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities).

 1. Перейдите к файлу ContentView вашего проекта в Xcode и создайте кнопку (Button)

```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack(spacing: 20) {

            Button(action: {
                LiveActivityManager.shared.startActivity()
            }, label: {
                Text("Start Live Activity")
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.blue)
                    .cornerRadius(10)
            })
        }
        .padding()
    }
}

#Preview {
    ContentView()
}
```
<img src="/ios-push-notifications-ios-live-activities-4.webp" alt=""/>

 2. Создайте файл LiveActivityManager.swift для управления Live Activities

```swift
import Foundation
import ActivityKit
import UIKit
import PushwooshFramework
import PushwooshLiveActivities

class LiveActivityManager: NSObject, ObservableObject {
    public static let shared: LiveActivityManager = LiveActivityManager()

    private var currentActivity: Activity<FoodDeliveryAttributes>? = nil

    override init() {
        super.init()
    }

    func startActivity() {
        guard ActivityAuthorizationInfo().areActivitiesEnabled else {
            print("You can't start live activity.")
            return
        }
        do {
            let pushwooshData = PushwooshLiveActivityAttributeData(activityId: "activity_id")
            let atttribute = FoodDeliveryAttributes(orderNumber: "1234567", pushwoosh: pushwooshData)
            let initialState = FoodDeliveryAttributes.ContentState(
                status: "Preparing your meal",
                estimatedTime: "25 min",
                emoji: "👨‍🍳",
                pushwoosh: nil
            )
            let activity = try Activity<FoodDeliveryAttributes>.request(
                attributes: atttribute,
                content: .init(state:initialState , staleDate: nil),
                pushType: .token
            )
            self.currentActivity = activity

            Task {
                for await pushToken in activity.pushTokenUpdates {
                    let pushTokenString = pushToken.reduce("") {
                        $0 + String(format: "%02x", $1)
                    }
                    print("Activity:\(activity.id) push token: \(pushTokenString)")

                    // MARK: - Send Push Token to Pushwoosh
                    Pushwoosh.LiveActivities.startLiveActivity(
                        token: pushTokenString,
                        activityId: "activity_id"
                    )
                }
            }
        } catch {
            print("Start Activity Error: \(error.localizedDescription)")
        }
    }
}

```

 3. Вот и все, теперь мы запускаем проект и нажимаем кнопку 'Start Live Activity'. Затем переходим на экран блокировки и видим созданную Live Activity.


<img src="/live-activities-1.webp" alt=""/>

### Запуск Live Activity с помощью удаленного push-уведомления

1.  Чтобы инициировать Live Activity через удаленное push-уведомление, вам необходимо отправить токен `pushToStartTokenUpdates` в Pushwoosh.

```swift
func getPushToStartToken() {
    if #available(iOS 17.2, *) {
        Task {
            for await data in Activity<LiveActivityAttributes>.pushToStartTokenUpdates {
                let token = data.map {String(format: "%02x", $0)}.joined()
                print("Activity PushToStart Token: \(token)")

                // Send `pushToStartTokenUpdates` token to Pushwoosh
                try await Pushwoosh.LiveActivities.sendPushToStartLiveActivity(token: token)
            }
        }
    }
}
```
2.  Инициируйте Live Activity с помощью удаленного push-уведомления

<Aside type="tip">
Следуйте нашему [справочнику по API Pushwoosh](/ru/developer/api-reference/ios-live-activities-api#startliveactivity) для получения инструкций и примеров по созданию запроса для удаленного запуска Live Activity.
</Aside>

### Управление Live Activities 

Pushwoosh iOS SDK предоставляет следующие методы для работы с Live Activities:

```swift
// Send Live Activity Push To Start Token to Pushwoosh
static func sendPushToStartLiveActivity(token: String)
static func sendPushToStartLiveActivity(token: String, completion: @escaping (Error?) -> Void)

// Start Live Activity Methods with Activity ID
static func startLiveActivity(token: String, activityId: String)
static func startLiveActivity(token: String, activityId: String, completion: @escaping (Error?) -> Void)

// Stop Live Activity Methods
static func stopLiveActivity()
static func stopLiveActivity(completion: @escaping (Error?) -> Void)

static func stopLiveActivity(activityId: String)
static func stopLiveActivity(activityId: String, completion: @escaping (Error?) -> Void)

// Schedule a Live Activity to start at a future date (iOS 26.0+)
static func schedule<Attributes: PushwooshLiveActivityAttributes>(attributes: Attributes, contentState: Attributes.ContentState, at startDate: Date, alertTitle: String, alertBody: String) throws -> Activity<Attributes>

// Cancel a scheduled or running Live Activity by its Activity ID (iOS 16.2+)
static func cancel<Attributes: PushwooshLiveActivityAttributes>(_ activityType: Attributes.Type, activityId: String)

```

Вы также можете обновлять Live Activities по сегментам, используя параметр Activity ID. При создании Activity вам необходимо передать в метод уникальный параметр Activity ID, который будет релевантен для определенного сегмента пользователей.

Например, N пользователей подписались на одно и то же событие в Live Activity. Необходимо, чтобы параметр Activity ID был уникальным для всех этих N пользователей.

Когда вы заканчиваете работу с Live Activity, используйте эти методы:
```swift
static func stopLiveActivity()
static func stopLiveActivity(completion: @escaping (Error?) -> Void)
```
<Aside type="note">
Вы можете управлять Live Activities для iOS через [Pushwoosh API](/ru/developer/api-reference/ios-live-activities-api).
</Aside>

### Планирование запуска Live Activity на будущую дату

<Aside type="note">
Требуется iOS 26.0+.
</Aside>

Вместо того чтобы запускать Live Activity немедленно, вы можете запланировать его запуск на будущую дату. `alertTitle` и `alertBody` показываются пользователю в локальном уведомлении, которое срабатывает, когда запланированная Activity фактически запускается:

```swift
if #available(iOS 26.0, *) {
    let startDate = Date().addingTimeInterval(3600) // starts in 1 hour

    do {
        let activity = try Pushwoosh.LiveActivities.schedule(
            attributes: atttribute,
            contentState: initialState,
            at: startDate,
            alertTitle: "Game starting!",
            alertBody: "The match is about to begin"
        )
        self.currentActivity = activity
    } catch {
        print("Schedule Activity Error: \(error.localizedDescription)")
    }
}
```

`startDate` должна быть в будущем, иначе вызов вызовет ошибку. Вызывайте `schedule` в основном потоке, когда приложение находится на переднем плане. Запроса к Pushwoosh во время планирования не происходит: сервер узнает об Activity, как только она фактически начнется и получит свой push-токен через тот же наблюдатель токенов, установленный методом `setup()` (см. ниже).

### Отмена Live Activity по Activity ID

<Aside type="note">
Требуется iOS 16.2+.
</Aside>

Используйте `cancel(_:activityId:)` для отмены Live Activity по его Activity ID, не имея ссылки на экземпляр `Activity`:

```swift
if #available(iOS 16.2, *) {
    Pushwoosh.LiveActivities.cancel(FoodDeliveryAttributes.self, activityId: "activity_id")
}
```

`cancel` немедленно завершает Activity на устройстве и уведомляет сервер Pushwoosh. Это отличается от `stopLiveActivity(activityId:)`, который только уведомляет сервер и не завершает Activity на устройстве напрямую. `cancel` также работает для Live Activity, которая была запланирована с помощью `schedule`, но еще не началась — она отменяется до своего запуска.

### Метод `Setup()`.
Pushwoosh упрощает передачу ID Activity, представляя функцию `PushwooshLiveActivities.setup`, которая обрабатывает весь жизненный цикл Live Activity в приложении. Эта функция автоматически прослушивает обновления токенов как `pushToStart`, так и `pushToUpdate`. Используя этот метод, приложению больше не нужно вручную отслеживать запуск Live Activities или управлять обновлениями токенов для обновлений Activity.

Мы рекомендуем использовать этот метод, поскольку он управляет всеми токенами на нашей стороне, уменьшая количество кода, которое вам нужно поддерживать на своей стороне. Это упрощает интеграцию и обеспечивает более плавный и эффективный опыт для вашего приложения.

В AppDelegate убедитесь, что вы импортировали `PushwooshFramework` и `PushwooshLiveActivities`, и вызовите метод `setup` из модуля `Pushwoosh.LiveActivities`.

**AppDelegate.swift**
```swift
if #available(iOS 16.1, *) {
    Pushwoosh.LiveActivities.setup(FoodDeliveryAttributes.self)
}
```
**FoodDeliveryAttributes**

```swift
import WidgetKit
import SwiftUI
import ActivityKit
import PushwooshFramework
import PushwooshLiveActivities

struct FoodDeliveryAttributes: PushwooshLiveActivityAttributes {
    public struct ContentState: PushwooshLiveActivityContentState {
        var status: String
        var estimatedTime: String
        var emoji: String
        var pushwoosh: PushwooshLiveActivityContentStateData?
    }

    var orderNumber: String
    var pushwoosh: PushwooshLiveActivityAttributeData
}
```
`FoodDeliveryAttributes`: Эта структура соответствует протоколу `PushwooshLiveActivityAttributes`. Она используется для определения атрибутов Live Activity в приложении.

<Aside type="note">
Вы можете управлять Live Activities и обновлять их контент с помощью метода /updateLiveActivity из Pushwoosh API. Для получения дополнительной информации, пожалуйста, прочтите [это руководство](/ru/developer/api-reference/ios-live-activities-api)
</Aside>

## Руководство по миграции

Начиная с версии 6.8.0 Pushwoosh iOS SDK, мы обновили структуру SDK. Методы Live Activities теперь доступны через модуль `PushwooshLiveActivities`.

Если вы использовали версию Pushwoosh iOS SDK ранее 6.8.0 и вызывали перечисленные ниже методы, а затем обновились до версии 6.8.0 или более поздней, обратите внимание на следующие изменения:

```swift
static func setup<Attributes: PushwooshLiveActivityAttributes>(_ activityType: Attributes.Type)
static func defaultSetup()
static func defaultStart(_ activityId: String, attributes: [String: Any], content: [String: Any])
```

Теперь для доступа к этим методам следует использовать модуль LiveActivity.

```swift
import PushwooshFramework
import PushwooshLiveActivities

```

```swift
Pushwoosh.LiveActivities.setup(FoodDeliveryAttributes.self)
Pushwoosh.LiveActivities.defaultSetup()
Pushwoosh.LiveActivities.defaultStart("activity_id",
                            attributes: ["key_attribute": "value_attribute"],
                            content: ["key_content": "value_content"])
```

Мы также сохранили поддержку методов через `Pushwoosh.sharedInstance()`, как указано ниже, но обратите внимание, что эти методы будут устаревшими в будущих выпусках.

``` swift
// Send Live Activity Push To Start Token to Pushwoosh
static func sendPushToStartLiveActivity(token: String)
static func sendPushToStartLiveActivity(token: String, completion: @escaping (Error?) -> Void)

// Start Live Activity Methods with Activity ID
static func startLiveActivity(token: String, activityId: String)
static func startLiveActivity(token: String, activityId: String, completion: @escaping (Error?) -> Void)

// Stop Live Activity Methods
static func stopLiveActivity()
static func stopLiveActivity(completion: @escaping (Error?) -> Void)

static func stopLiveActivity(activityId: String)
static func stopLiveActivity(activityId: String, completion: @escaping (Error?) -> Void)
```