--- title: iOS / macOS SDK --- # iOS / macOS SDK Apple 平台 SDK,支援 **iOS 15+** 與基於 Mac Catalyst 的 **macOS 11+(Big Sur)**,以 `.xcframework` 加本地化資源 `.bundle` 形式發布。SwiftUI / UIKit / AppKit 專案皆可直接接入。 ## GitHub 上的範例 ::: tip 📦 [Captcha-La/iosmacos-demo](https://github.com/Captcha-La/iosmacos-demo) — 完整可執行範例,包含所有整合步驟。 ::: ## 安裝 在 `Podfile` 加入 CaptchaLa(CocoaPods 1.10+): ```ruby # Podfile platform :ios, '13.0' target 'YourApp' do use_frameworks! pod 'Captchala', '~> 1.0.2' end ``` ```bash pod install ``` 如果你偏好手動整合: 從 [CaptchaLa 控制台](https://dash.captcha.la) 下載最新 iOS 版本,壓縮檔內含: - `Captchala.xcframework` — 已編譯的 SDK - `Captchala.bundle` — 本地化資源 將兩者放在你的 `.xcodeproj` 旁。demo 專案以檔名引用,只要位置不變,無需額外手動連結。 手動整合請直接下載 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` | 共享單例,所有入口皆透過它存取。 | | `CaptchalaConfigBuilder()` | 鏈式 Builder,用於設定 `appKey`、`action`、`lang`、`theme`、`enableVoice`、`enableOfflineMode`、`serverToken`。 | | `initialize(config:)` | 套用已建立的設定。回傳 `self`,便於串接 `setDelegate`。 | | `setDelegate(_:)` | 傳入實作 `CaptchalaDelegate` 的 `NSObject`。SDK 持弱引用。 | | `verify(from: presenter)` | 在指定的 UIViewController 上顯示驗證碼(iOS / Catalyst),SDK 彈出 modal sheet。 | | `CaptchalaResult` | 透過 `captcha(didSucceedWith:)` 回呼回傳。欄位:`passToken`、`challengeId`、`ttl`、`isOffline`、`isClientOnly`。 | | `onServerTokenExpired { … }` | 非同步閉包,當前 `server_token` 在挑戰過程中過期時,自動取得新 token。 | ## 伺服器端驗證 將 `result.passToken`(或 `result.token`)送到你的後端,再呼叫 CaptchaLa API 驗證。**切勿在用戶端程式碼中暴露 `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": "" } ``` 完整驗證端點及 `X-App-Key` / `X-App-Secret` 流程請見 [API 參考](../api-reference)。 ## 常見問題 - **找不到 `Captchala.xcframework`** `.xcframework` 與 `.bundle` 必須和 `Example.xcodeproj` 同層。demo 透過檔名引用它們,更新 SDK 時保持位置不變即可。 - **找不到 Mac Catalyst destination** 在 Xcode 中,於 target 的 *Supported Destinations* 勾選 *Mac (Mac Catalyst)*。demo target 預設 `SUPPORTS_MACCATALYST = YES`。 - **modal 沒有彈出** `verify(from:)` 必須傳入實際的 `UIViewController`。demo 走訪 `UIApplication.connectedScenes` 找最上層的 key-window controller,如果只有 SwiftUI `View`,複製這段 helper 即可。 - **macOS 上需要 `Info.plist` 隱私描述** 針對 Catalyst / 原生 macOS target,開啟 **Outgoing Connections (Client)** 沙箱權限。SDK 僅發起 HTTPS 請求,不存取麥克風或攝影機。 ## 系統需求 - iOS 15+(實體裝置或模擬器) - macOS 11+(Big Sur)透過 Mac Catalyst;原生 target 需 macOS 13+ - Xcode 15+ - Swift 5.7+(async/await)