Mobile SDK для native iOS
Эта инструкция относится к ShopStoryPlayerSDK 0.2.0-preview.2. Требуются iOS 15+, Xcode 16+ и read-only доступ к пакету. Для другой версии используйте её README и migration notes: версии и выпуск.
Установить SDK
В Xcode откройте File → Add Package Dependencies, вставьте URL из выданного доступа и выберите Exact Version: 0.2.0-preview.2. Добавьте product ShopStoryPlayerSDK в app target. Сохраните Package.resolved в репозитории приложения.
Если проект использует CocoaPods, возьмите Podfile из инструкции к этой версии пакета. Не добавляйте токен в URL, Package.swift или Podfile.
До запуска получите applicationId, один feedProductId с опубликованным VOD и один ID без видео. SDK использует реальные данные проекта; произвольные значения не создают demo-каталог.
Запустить starter
Скачать iOS starter. В архиве — app target, экран товара и SDK player. README описывает размещение приватного пакета рядом с проектом и запуск без клиентских данных.
После настройки откройте тестовый товар. Для активного видео должен появиться SDK entrypoint; нажатие открывает player. Для товара без видео entrypoint отсутствует. Ошибка SDK сохраняет экран товара рабочим.
Starter проверяет первое воспроизведение и передачу product action приложению. Корзину он не изменяет. Перенос активной сессии в Follow Me подключается отдельно по примеру ниже.
Configure и video lookup
import ShopStoryPlayerSDK
private let shopStory = ShopStorySDK.shared
@MainActor
private var shopStoryConfigured = false
@MainActor
private var productStateRequest: ShopStoryProductStreamStateRequest?
@MainActor
func configureShopStory() {
do {
try shopStory.configure(
applicationId: applicationId,
hostAppVersion: Bundle.main.object(
forInfoDictionaryKey: "CFBundleShortVersionString"
) as? String
)
shopStoryConfigured = true
} catch {
shopStoryConfigured = false
hideShopStoryEntrypoint()
reportIntegrationError(error)
}
}
@MainActor
func clearShopStoryProduct() {
productStateRequest?.cancel()
productStateRequest = nil
hideShopStoryEntrypoint()
}
@MainActor
func loadShopStory(for product: Product) {
clearShopStoryProduct()
guard shopStoryConfigured else { return }
shopStory.setCurrentSurface(.productDetail)
productStateRequest = shopStory.loadProductStreamState(
feedProductId: product.feedProductId
) { result in
switch result {
case let .success(.active(entrypoint)):
showShopStoryEntrypoint(entrypoint)
case .success(.unavailable):
hideShopStoryEntrypoint()
case let .failure(error):
hideShopStoryEntrypoint()
reportIntegrationError(error)
}
}
}
Вызывайте конфигурацию один раз при запуске приложения. Ошибка оставляет ShopStory UI скрытым и не прерывает запуск приложения. При смене товара сначала отмените запрос и уберите прежний entrypoint, затем запрашивайте видео нового товара. При закрытии PDP вызовите clearShopStoryProduct(). .unavailable означает отсутствие доступного видео; .failure(error) передавайте в диагностический logger приложения. Полученный entrypoint передавайте в coordinator целиком; не собирайте player URL вручную.
Full-screen player и Follow Me
Lookup из предыдущего примера только получает entrypoint. Для воспроизведения host app выполняет ещё шесть действий:
- Root integration owner создаёт и удерживает одну playback session, один
ShopStoryPlayerCoordinatorи floating-player controller. - Full-screen container вызывает
coordinator.attach(to:), затемcoordinator.load(entrypoint:). - Coordinator delegate принимает типизированные product actions и lifecycle events.
- При переходе из player в native PDP host отсоединяет player view без teardown, открывает PDP и монтирует ту же сессию в follow-me container.
- После каждого route transition host вызывает
setCurrentSurfaceи применяетshouldShowFollowMePlayer()к активной сессии: показывает или скрывает container и синхронизирует playback state. teardown()вызывается при закрытии, завершении сессии или remote disable. Product handoff между full-screen и follow-me не завершает сессию.
Создавайте ShopStoryPlaybackOwner после успешного configure, когда начинается активная playback session. Root integration owner приложения удерживает этот объект до stop().
import ShopStoryPlayerSDK
import UIKit
@MainActor
final class ShopStoryPlaybackOwner: ShopStoryPlayerCoordinatorDelegate {
private let sdk = ShopStorySDK.shared
private let floatingController = ShopStorySDK.shared.makeFloatingPlayerController()
private(set) lazy var coordinator = ShopStoryPlayerCoordinator(delegate: self)
func start(entrypoint: ShopStoryProductDetailEntrypoint, in container: UIView) {
coordinator.attach(to: container)
coordinator.load(entrypoint: entrypoint)
}
func moveToFollowMe(
in container: UIView,
surface: ShopStorySurface,
mediaOrientation: ShopStoryMediaOrientation
) {
coordinator.detach()
coordinator.attach(to: container)
reconcile(surface: surface, mediaOrientation: mediaOrientation)
}
func shopStoryPlayerCoordinator(
_ coordinator: ShopStoryPlayerCoordinator,
didReceive action: ShopStoryProductAction
) {
guard let feedProductId = action.payload.feedProductId,
!feedProductId.isEmpty else {
reportInvalidProductAction(action)
return
}
handleProductAction(action.kind, feedProductId: feedProductId)
}
func reconcile(
surface: ShopStorySurface,
mediaOrientation: ShopStoryMediaOrientation
) {
sdk.setCurrentSurface(surface)
if sdk.shouldShowFollowMePlayer() {
let geometry = sdk.followMeGeometry(mediaOrientation: mediaOrientation)
floatingController.show(using: geometry)
coordinator.resumePlayback()
} else {
coordinator.pausePlayback(reason: .surfaceBlocked)
floatingController.suppress()
}
}
func shopStoryPlayerCoordinator(
_ coordinator: ShopStoryPlayerCoordinator,
didUpdate event: ShopStoryPlayerLifecycleEvent
) {
handlePlayerLifecycle(event)
}
func stop() {
floatingController.close()
coordinator.teardown()
}
}
handleProductAction, handlePlayerLifecycle и нативные контейнеры принадлежат приложению. После принятого перехода на PDP приложение монтирует follow-me container и вызывает moveToFollowMe. В этот метод передаётся контейнер, в котором SDK-компонент размещает coordinator.playerView. При переносе не вызывайте load или teardown: используется тот же coordinator и его player view. Полная схема контейнеров и их освобождения входит в руководство к поставленной версии SDK.
Следующий шаг
Подключите lifecycle и product actions, затем аналитику приложения.