--- title: iOS / macOS SDK --- # iOS / macOS SDK SDK для платформ Apple для **iOS 15+** и **macOS 11+ (Big Sur)** через Mac Catalyst, поставляется как `.xcframework` плюс `.bundle` локализованных ресурсов. Готовое решение для проектов SwiftUI, UIKit и AppKit. ## Демо на GitHub ::: tip 📦 [Captcha-La/iosmacos-demo](https://github.com/Captcha-La/iosmacos-demo) — полный рабочий пример со всеми шагами интеграции. ::: ## Установка Добавьте CaptchaLa в ваш `Podfile` (CocoaPods 1.10+): ```ruby # Podfile platform :ios, '13.0' target 'YourApp' do use_frameworks! pod 'Captchala', '~> 1.0.2' end ``` ```bash pod install ``` Или, если вы предпочитаете ручную интеграцию: Скачайте последний релиз для iOS из [панели управления CaptchaLa](https://dash.captcha.la). Архив содержит: - `Captchala.xcframework` — скомпилированный SDK - `Captchala.bundle` — локализованные ресурсы Поместите оба рядом с вашим `.xcodeproj`. Демо-проект ссылается на них по имени файла; помимо сохранения их расположения, никакого ручного связывания не требуется. Для ручной интеграции скачайте xcframework напрямую: [dash.captcha.la/downloads](https://dash.captcha.la/downloads) ```text YourApp/ ├── YourApp.xcodeproj ├── YourApp/ ├── Captchala.xcframework └── Captchala.bundle ``` Откройте проект и запустите в симуляторе, на устройстве или в **My Mac (Mac Catalyst)**: ```bash open YourApp.xcodeproj # Cmd-R in Xcode ``` ## Быстрый старт ```swift import SwiftUI import Captchala final class CaptchaDelegateBridge: NSObject, CaptchalaDelegate { var onSuccess: ((CaptchalaResult) -> Void)? var onFailure: ((CaptchalaError) -> Void)? var onClose: (() -> Void)? func captcha(didSucceedWith result: CaptchalaResult) { onSuccess?(result) } func captcha(didFailWithError error: CaptchalaError) { onFailure?(error) } func captchaDidClose() { onClose?() } } struct LoginView: View { @State private var bridge = CaptchaDelegateBridge() @State private var status = "Tap to verify" var body: some View { Button("Verify with CAPTCHA", action: startVerify) Text(status).font(.caption) } private func startVerify() { bridge.onSuccess = { r in // Send r.passToken to your backend for validation. status = "OK: \(r.passToken)" } bridge.onFailure = { e in status = "ERROR [\(e.code)] \(e.message)" } Task { @MainActor in // 1. Fetch a one-shot server_token from YOUR backend. let token = await fetchServerTokenFromYourBackend() // 2. Build config and present. let config = CaptchalaConfigBuilder() .appKey("YOUR_APP_KEY") .action("login") .lang("en") // en, zh-CN, zh-TW, ja, ko, ms, vi, id .theme("light") // "light" | "dark" .enableVoice(true) .enableOfflineMode(true) .serverToken(token) .onServerTokenExpired { await fetchServerTokenFromYourBackend() } .build() guard let presenter = topViewController() else { return } CaptchalaClient.shared .initialize(config: config) .setDelegate(bridge) .verify(from: presenter) } } } ``` ::: tip Mac Catalyst и нативный macOS Один и тот же код Swift работает на iOS, Mac Catalyst и нативном macOS. На Catalyst передайте любой `UIViewController`. На нативном macOS используйте `NSViewController` и вызывайте `.verify()` без аргумента — SDK откроет собственное `NSWindow`. ::: ## Поверхность API | Символ | Назначение | | --- | --- | | `CaptchalaClient.shared` | Общий singleton. Все точки входа идут через него. | | `CaptchalaConfigBuilder()` | Fluent builder. Задайте `appKey`, `action`, `lang`, `theme`, `enableVoice`, `enableOfflineMode`, `serverToken`. | | `initialize(config:)` | Применяет собранную конфигурацию. Возвращает `self`, чтобы можно было сцепить `setDelegate`. | | `setDelegate(_:)` | Предоставьте `NSObject`, соответствующий `CaptchalaDelegate`. SDK хранит слабую ссылку. | | `verify(from: presenter)` | Показывает CAPTCHA поверх указанного UIViewController (iOS / Catalyst). SDK добавляет модальный sheet. | | `CaptchalaResult` | Возвращается через `captcha(didSucceedWith:)`. Поля: `passToken`, `challengeId`, `ttl`, `isOffline`, `isClientOnly`. | | `onServerTokenExpired { … }` | Асинхронное замыкание, которое заново получает свежий `server_token`, если предыдущий истёк в середине запроса. | ## Серверная проверка Перешлите `result.passToken` (или `result.token`) на ваш backend и проверьте его через API CaptchaLa. Никогда не размещайте `X-App-Secret` в клиентском коде. ```bash POST https://apiv1.captcha.la/v1/validate X-App-Key: YOUR_APP_KEY X-App-Secret: YOUR_APP_SECRET Content-Type: application/json { "pass_token": "" } ``` См. [Справочник API](../api-reference) для полного endpoint проверки и потока `X-App-Key` / `X-App-Secret`. ## Устранение неполадок - **`Captchala.xcframework` не найден** `.xcframework` и `.bundle` должны находиться рядом с `Example.xcodeproj`. Демо ссылается на оба по имени файла; сохраняйте их расположение при обновлении SDK. - **Отсутствует назначение Mac Catalyst** В Xcode включите *Mac (Mac Catalyst)* в *Supported Destinations* вашего target. Demo-target поставляется с `SUPPORTS_MACCATALYST = YES`. - **Модальное окно не появляется** Передайте реальный `UIViewController` в `verify(from:)`. Демо проходит `UIApplication.connectedScenes`, чтобы найти верхний активный контроллер key-window — скопируйте этот helper, если у вас только SwiftUI `View`. - **Строки конфиденциальности в `Info.plist` на macOS** Для целей Catalyst / нативного macOS включите sandbox capability **Outgoing Connections (Client)**. SDK делает только HTTPS-вызовы, без доступа к микрофону или камере. ## Требования - iOS 15+ (устройство или симулятор) - macOS 11+ (Big Sur) через Mac Catalyst, macOS 13+ для нативных целей - Xcode 15+ - Swift 5.7+ (async/await)