--- title: SDK iOS / macOS --- # SDK iOS / macOS SDK para plataformas Apple compatível com **iOS 15+** e **macOS 11+ (Big Sur)** via Mac Catalyst, distribuído como um `.xcframework` acompanhado de um `.bundle` de recursos localizados. Pronto para SwiftUI, UIKit e AppKit. ## Demonstração no GitHub ::: tip 📦 [Captcha-La/iosmacos-demo](https://github.com/Captcha-La/iosmacos-demo) — exemplo executável completo com cada passo de integração. ::: ## Instalação Adicione a CaptchaLa ao seu `Podfile` (CocoaPods 1.10+): ```ruby # Podfile platform :ios, '13.0' target 'YourApp' do use_frameworks! pod 'Captchala', '~> 1.0.2' end ``` ```bash pod install ``` Ou, se preferir integração manual: Baixe a versão iOS mais recente no [painel da CaptchaLa](https://dash.captcha.la). O arquivo contém: - `Captchala.xcframework` — o SDK compilado - `Captchala.bundle` — recursos localizados Coloque ambos ao lado do seu `.xcodeproj`. O projeto da demo os referencia pelo nome do arquivo; nenhum vínculo manual é necessário além de manter a localização estável. Para integração manual, baixe o xcframework diretamente em: [dash.captcha.la/downloads](https://dash.captcha.la/downloads) ```text YourApp/ ├── YourApp.xcodeproj ├── YourApp/ ├── Captchala.xcframework └── Captchala.bundle ``` Abra o projeto e execute no simulador, em um dispositivo, ou em **My Mac (Mac Catalyst)**: ```bash open YourApp.xcodeproj # Cmd-R in Xcode ``` ## Início rápido ```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 e macOS nativo Exatamente o mesmo código Swift roda em iOS, Mac Catalyst e macOS nativo. No Catalyst, passe qualquer `UIViewController`. No macOS nativo, use `NSViewController` e chame `.verify()` sem argumento — o SDK exibe em sua própria `NSWindow`. ::: ## Superfície da API | Símbolo | Função | | --- | --- | | `CaptchalaClient.shared` | Singleton compartilhado. Todos os pontos de entrada partem dele. | | `CaptchalaConfigBuilder()` | Builder fluente. Defina `appKey`, `action`, `lang`, `theme`, `enableVoice`, `enableOfflineMode`, `serverToken`. | | `initialize(config:)` | Aplica a configuração construída. Devolve `self` para permitir encadear `setDelegate`. | | `setDelegate(_:)` | Forneça um `NSObject` que conforma a `CaptchalaDelegate`. O SDK mantém uma referência fraca. | | `verify(from: presenter)` | Apresenta o CAPTCHA sobre o UIViewController fornecido (iOS / Catalyst). O SDK exibe uma folha modal. | | `CaptchalaResult` | Retornado via `captcha(didSucceedWith:)`. Campos: `passToken`, `challengeId`, `ttl`, `isOffline`, `isClientOnly`. | | `onServerTokenExpired { … }` | Closure assíncrona que busca um novo `server_token` se o anterior expirar no meio do desafio. | ## Validação no servidor Encaminhe `result.passToken` (ou `result.token`) ao seu backend e valide-o contra a API da CaptchaLa. Nunca exponha `X-App-Secret` em código de cliente. ```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": "" } ``` Veja a [Referência da API](/pt-BR/api-reference) para o endpoint completo de validação e o fluxo `X-App-Key` / `X-App-Secret`. ## Solução de problemas - **`Captchala.xcframework` não encontrado** O `.xcframework` e o `.bundle` precisam estar ao lado de `Example.xcodeproj`. A demo referencia ambos pelo nome do arquivo; mantenha a localização estável ao atualizar o SDK. - **Destino Mac Catalyst ausente** No Xcode, habilite *Mac (Mac Catalyst)* em *Supported Destinations* do seu target. O target da demo vem com `SUPPORTS_MACCATALYST = YES`. - **A modal não aparece** Passe um `UIViewController` real para `verify(from:)`. A demo percorre `UIApplication.connectedScenes` para localizar o controller da key-window ativa mais ao topo — copie esse helper se você tiver apenas uma `View` em SwiftUI. - **Strings de privacidade no `Info.plist` no macOS** Para targets Catalyst / macOS nativo, habilite a capacidade de sandbox **Outgoing Connections (Client)**. O SDK só faz chamadas HTTPS, sem acesso a microfone ou câmera. ## Requisitos - iOS 15+ (dispositivo ou simulador) - macOS 11+ (Big Sur) via Mac Catalyst, macOS 13+ para targets nativos - Xcode 15+ - Swift 5.7+ (async/await)