# TencentQianWebView — iOS Swift SDK Framework

腾讯电子签 H5 容器 SDK iOS Swift 实现的 Framework 源码目录，对应 Xcode 工程中的 `TencentQianWebView` framework target。

## 模块标识

| 项 | 值 |
|---|---|
| 模块名 | `TencentQianWebView` |
| 语言 | Swift 5.9 |
| Deployment Target | iOS 14.3 |
| 内核 | WKWebView |
| 分发方式 | XcodeGen 工程（`ios-swift/project.yml`） + Swift Package Manager（仓库根 `Package.swift`） |

## 目录结构

```
TencentQianWebView/
├── Sources/
│   ├── TencentQianWebView.swift              # 容器模式公共入口（命名空间 enum）
│   ├── TencentQianWebViewController.swift    # 容器内置 ViewController
│   ├── TencentQianWebViewConfigurator.swift  # 配置模式公共入口
│   ├── TencentQianWebViewComponent.swift     # 组件模式（嵌入自定义布局，含嵌套 Controller）
│   ├── TencentQianWebViewPrewarmer.swift    # 预热公共入口（configure/prewarm/releaseAll）
│   ├── TencentQianWebViewShared.swift        # 共享 WKProcessPool 等
│   ├── Configuration/                        # WKWebViewConfiguration 工厂
│   ├── Internal/                             # navigation / UI delegate / Prewarm（池/manifest/去重）
│   ├── Download/                             # 下载策略 + URLSession + 分享 sheet
│   ├── Scheme/                               # qianapp / 外部 scheme 拦截
│   ├── Model/                                # Config / SignResult / SignCallbacks / SdkEvent / Prewarm*
│   └── Resources/                            # 国际化字符串（Base / zh-Hans）
└── Info.plist
```

## 公共 API 速览

### 容器模式 `TencentQianWebView.open`

SDK 内置承载 VC（含顶栏、进度条、关闭确认、安全区适配），一次调用即可拉起签署 H5：

```swift
import TencentQianWebView

TencentQianWebView.open(
    from: self,
    url: signUrl,
    config: TencentQianWebViewConfig(topBarTitle: "电子签署"),
    callbacks: SignCallbacks(onSignResult: { result in
        // result.action / result.result / result.flowId / result.extras
    })
)
```

### 组件模式 `TencentQianWebViewComponent`

将签署 WebView 嵌入宿主自定义布局，顶栏 / 进度条 / 错误页由宿主自绘。参数面与 Android 同名（除 `reusePrewarmPool`，iOS 无此参数）；命令对象为嵌套类型 `TencentQianWebViewComponent.Controller`（`TencentQianWebViewController` 已被容器模式占用）：

```swift
let controller = TencentQianWebViewComponent.Controller()

let component = TencentQianWebViewComponent(
    url: signUrl,
    config: TencentQianWebViewConfig(topBarTitle: "电子签署"),
    onSignResult: { result in /* 处理签署结果 */ },
    onTitleChanged: { title, canGoBack in /* 更新自绘顶栏标题 */ },
    onProgressChanged: { progress, visible in /* 显示/更新进度条 */ },
    onRenderUnrecoverable: { /* 显示错误页 + controller.reload() 重试 */ },
    controller: controller
)

myView.addSubview(component)  // + Auto Layout 约束

// 页面销毁时（viewDidDisappear 确认退出 / deinit）：component.release()
```

> iOS `WKWebView` 无 `clearHistory` API，池实例永不复用到页面，故组件**无 `reusePrewarmPool` 参数**。崩溃恢复复用容器模式内核（原地 `load` 恢复，非 Android 销毁重建）。完整参数面与关键约束详见 [../../docs/usage-guide.md §1.5](../../docs/usage-guide.md#15-组件模式嵌入自定义布局)。

### 配置模式 `TencentQianWebViewConfigurator.apply`

把 SDK 能力叠加到客户已有 `WKWebView` 上，保留客户自有 UI 与导航：

```swift
final class MyWebViewController: UIViewController {
    private let webView = WKWebView()
    private var handle: TencentQianWebViewConfigurator.Handle?  // 必须强引用持有

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(webView)

        handle = TencentQianWebViewConfigurator.apply(
            webView: webView,
            hostController: self,
            config: TencentQianWebViewConfig(),
            callbacks: SignCallbacks(onSignResult: { result in /* ... */ })
        )
        webView.load(URLRequest(url: signUrl))
    }
}
```

退出页面 `handle.detachAndDestroy()` 解绑并销毁；复用 WebView 则用 `handle.detach()` 仅解绑 SDK 注入。

### 预热（可选，提升首屏速度）

预热与容器/配置模式**正交**，不预热时行为与现状完全一致，预热是纯增量收益。`configure()` 可省（首次 `prewarm` 会以默认 `PROD` 懒初始化）；`MINIMAL` 仅 DNS、收益小，真正提速靠 `LIGHT` / `HEAVY`，按意图触发即可：

```swift
// 进入签署业务入口前
TencentQianWebViewPrewarmer.configure(PrewarmConfig(environment: .prod))
TencentQianWebViewPrewarmer.prewarm(.light, bizType: "single-sign")
TencentQianWebViewPrewarmer.prewarm(.heavy, bizType: "single-sign")

// 签署流程结束、不再需要时主动释放预热池实例（页面 WebView 关闭即销毁，无需手动回收）
TencentQianWebViewPrewarmer.releaseAll()
```

> iOS `WKWebView` 无 `clearHistory` API，池实例只加载 `warmup.html` 做网络/进程预热，**永不复用到页面**；预热收益靠共享 `WKProcessPool`（进程复用）+ `.default()` DataStore（磁盘缓存跨实例命中）承接。

完整档位语义、触发时机、池生命周期与端差异详见 [../../docs/usage-guide.md §3.5](../../docs/usage-guide.md#35-预热可选提升首屏速度)。

## 单元测试

```bash
bash scripts/test-ios-swift.sh
```

测试 target 见同级 `../TencentQianWebViewTests/`，使用 XCTest。

## SPM 集成

仓库根 [`Package.swift`](../../Package.swift) 暴露 `TencentQianWebView` library product，客户可直接通过 SPM 引入：

```swift
.package(url: "<your-git-url>", from: "1.0.0"),
.product(name: "TencentQianWebView", package: "h5-in-app-integration"),
```

## 关键设计点

- **共享 `WKProcessPool` 单例**：`TencentQianWebViewShared.processPool`，所有 SDK 创建的 `WKWebView` 共用，保证多 WebView 间 Cookie 互通
- **UA 同步注入**：`WKConfigurationFactory.makeConfiguration` 通过 `applicationNameForUserAgent` 同步追加 `qianwv/<version>`，无时序竞争
- **下载策略**：`WKNavigationDelegate.decidePolicyFor navigationResponse` 识别下载 → `URLSession` 下载到沙盒 → `UIActivityViewController` 让用户分享 / 保存

## 集成与排错

- 接入指南：[../../docs/usage-guide.md](../../docs/usage-guide.md)
- 接入自检清单：[../../docs/integration-checklist.md](../../docs/integration-checklist.md)
- 排错决策树 + FAQ：[../../docs/troubleshooting.md](../../docs/troubleshooting.md)
- `qianapp://` 协议规范：[../../docs/qianapp-protocol.md](../../docs/qianapp-protocol.md)
