XuqmGroup-iOSSDK/README.md
XuqmGroup 5b34c60838 feat(sdk): 新增文件上传下载功能并完善WebView组件
- 在Android SDK中新增FileSDK模块,提供统一的文件上传、下载、打开接口
- 实现Android端文件下载到沙盒目录或公共Downloads目录,并支持通知栏进度显示
- 完善Android WebView组件,增加文件选择、拍照、下载拦截、H5双向通信能力
- 在iOS SDK中新增XuqmFileSDK模块,提供文件上传下载功能
- 实现iOS端WebView组件的文件下载拦截和原生文件选择器集成
- 更新文档说明Android和iOS SDK的文件操作API使用方法
- 重构iOS SDK项目结构,按功能拆分为多个独立模块便于集成
- 添加文件下载进度通知和完成后的文件打开功能
2026-06-05 15:48:08 +08:00

9.8 KiB

XuqmGroup iOS SDK 文档

Swift 5.9 · iOS 16+ · macOS 13+ · async/await

模块结构

XuqmGroup-iOSSDK/
├── Package.swift              # SPM 包定义
├── XuqmSDK.podspec            # CocoaPods 发版描述
├── XuqmWebViewSDK.podspec     # WebView 独立模块发版描述
├── PUBLISH.md                 # 发版操作手册
├── Sources/XuqmCoreSDK/       # 核心初始化、HTTP、Token
├── Sources/XuqmImSDK/         # IMWebSocket 实时通信
├── Sources/XuqmPushSDK/       # 推送APNs Token 注册
├── Sources/XuqmUpdateSDK/     # 版本管理:检查更新
├── Sources/XuqmLicenseSDK/    # 授权管理
├── Sources/XuqmFileSDK/       # 文件上传、下载、本地打开
└── Sources/XuqmWebViewSDK/    # WebView 嵌入式组件 / 独立页面
    ├── XWebViewBridge.swift   # 页面配置 / 控制器桥接
    ├── XWebViewPage.swift     # 独立页面
    ├── XWebViewTypes.swift    # 配置 / 控制器协议
    └── XWebViewView.swift     # 嵌入式组件

集成

Swift Package Manager推荐

在 Xcode → File → Add Package Dependencies,输入仓库地址

https://xuqinmin.com/xuqinmin12/XuqmGroup-iOSSDK.git

选择版本规则 Up to Next Major: 0.1.0

或在 Package.swift 中添加:

dependencies: [
    .package(url: "https://xuqinmin.com/xuqinmin12/XuqmGroup-iOSSDK.git", from: "0.1.0")
],
targets: [
    .target(name: "YourApp", dependencies: ["XuqmSDK", "XuqmWebViewSDK"])
]

CocoaPods

# Podfile
source 'https://xuqinmin.com/xuqinmin12/xuqm-specs.git'
source 'https://cdn.cocoapods.org/'

pod 'XuqmSDK', '~> 0.1.0'
pod 'XuqmWebViewSDK', '~> 0.1.0'

快速开始

1. 初始化AppDelegate / @main

import XuqmSDK

@main
struct MyApp: App {
    init() {
        XuqmSDK.initialize(
            appKey: "ak_your_app_key",
            appSecret: "as_your_app_secret",
            debug: true
        )
    }
}

2. 登录后存储 Token

// 调用你的业务登录接口获得 token
await XuqmSDK.setToken(token)

3. WebView 独立模块

XuqmWebViewSDK 不需要单独初始化,直接依赖即可使用。

import XuqmWebViewSDK

// 嵌入式组件:直接放到任意 SwiftUI 页面中
XWebViewView(
    config: XWebViewConfig(
        url: "https://example.com",
        title: "嵌入式网页"
    )
)

// 独立页面:在导航栈中直接 push
NavigationLink("打开页面模式") {
    XWebViewPage(
        config: XWebViewConfig(
            url: "https://example.com",
            title: "独立页面"
        )
    )
}

Core

ApiClient

基于 URLSession,async/await,自动附加 Bearer Token,统一解析 ApiResponse<T>

// 定义响应模型
struct LoginResponse: Decodable {
    let token: String
}

// 发起请求
let response: LoginResponse = try await ApiClient.post(
    path: "/api/im/auth/login",
    body: ["appKey": appKey, "userId": userId]
)

TokenStore

基于 Keychain 存储(kSecClassGenericPassword,App 重启后自动恢复。

await XuqmSDK.setToken("eyJ...")    // 存储
let token = XuqmSDK.getToken()      // 读取(同步)
await XuqmSDK.setToken(nil)         // 清除(登出)

IM

ImClient

import XuqmSDK

class ChatViewController: UIViewController, ImEventDelegate {

    let imClient = ImClient()

    override func viewDidLoad() {
        super.viewDidLoad()
        imClient.delegate = self
        imClient.connect()
    }

    // 发送消息
    func sendMessage() throws {
        try imClient.send(SendMessageParams(
            toId: "user_002",
            chatType: .single,
            msgType: .text,
            content: "Hello!"
        ))
    }

    // 撤回消息
    func revokeMessage(msgId: String) throws {
        try imClient.revoke(msgId: msgId)
    }

    deinit { imClient.disconnect() }
}

// MARK: - ImEventDelegate
extension ChatViewController {
    func onConnected() { print("IM 连接成功") }
    func onDisconnected(code: Int, reason: String) { print("断开: \(code)") }
    func onMessage(_ msg: ImMessage) { /* 更新 UI */ }
    func onRevoke(msgId: String, operatorId: String) { /* 标记消息已撤回 */ }
    func onError(_ error: Error) { print("错误: \(error)") }
}

ImMessage 结构

public struct ImMessage: Decodable {
    public let id: String
    public let fromId: String
    public let toId: String
    public let chatType: ChatType      // single / group
    public let msgType: MsgType
    public let content: String
    public let extra: String?
    public let revoked: Bool
    public let createdAt: String
    public let editedAt: Int64?
}

消息类型MsgType

text / image / video / audio / file / custom / location / notify / richText / callAudio / callVideo / forward

自动重连

断线后指数退避重连,初始 3s,最大 30s。disconnect() 后停止。


Push

import XuqmSDK

// 在 didRegisterForRemoteNotificationsWithDeviceToken 中调用
func application(_ application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Task {
        let token = deviceToken.map { String(format: "%02x", $0) }.joined()
        try await PushSDK.registerToken(
            token,
            userId: "user_001"
        )
    }
}

PushSDK.registerToken 内部将 Data 转换为十六进制字符串,vendor 固定为 APNS


Update

检查原生版本更新

import XuqmSDK

let result = try await UpdateSDK.checkAppUpdate(currentVersionCode: 123)
if result.needsUpdate, let info = result.info {
    print("最新版本: \(info.versionName)")
    // iOS 只能跳转 App Store
    if let url = URL(string: info.appStoreUrl) {
        await UIApplication.shared.open(url)
    }
}

UpdateSDK 这里只负责 iOS App 版本更新。RN 热更新如果需要,走独立的 RN SDK / RN 更新模块,不并入统一发版能力。

XuqmWebViewSDK 提供独立的 WebView 组件和页面,可与 XuqmSDK 同时使用,也可单独依赖。


XuqmFileSDK

文件上传、下载、本地打开的统一入口。XuqmImSDKXuqmWebViewSDK 均依赖此模块。

上传

import XuqmFileSDK

let result: FileUploadResult = try await FileSDK.shared.upload(
    fileURL: localFileURL,
    thumbnailData: thumbnailJpegData  // 可选
)
// result.url / .thumbnailUrl / .hash / .size / .mimeType / .ext

下载

// 下载存储目标
public enum FileDownloadDestination: Sendable {
    case sandbox   // App Documents 目录(在 Files App 中以 App 名称显示)
    case userPick  // 弹出系统存储面板,由用户选择保存位置
}

// URL 下载,实时进度回调
let localURL: URL = try await FileSDK.shared.download(
    url: "https://example.com/report.pdf",
    fileName: "report.pdf",          // 可选,默认从 URL 推断
    destination: .sandbox,
    onProgress: { progress in        // 0–100
        print("下载进度:\(progress)%")
    }
)

// Blob / base64 数据写盘
let localURL: URL = try FileSDK.shared.saveBlobDownload(
    base64Data: b64String,
    fileName: "export.xlsx",
    destination: .userPick
)

XuqmWebViewSDK

XWebViewConfig 完整参数

参数 类型 默认值 说明
url String "" 初始加载地址
title String "" 页面标题(独立页面模式使用)
hideToolbar Bool false 隐藏独立页面顶栏
hideStatusBar Bool false 隐藏状态栏
userAgent String? nil 自定义 User-Agent
injectedJavaScript String? nil 页面加载后注入的额外 JS
downloadDestination FileDownloadDestination .sandbox 下载文件存储目标
onMessage (String) -> Void? nil H5 发送消息的回调

文件选择与拍照

WKWebView 原生支持 <input type="file">,SDK 额外处理:

  • <input type="file" capture> 摄像头iOS 15+ 通过 requestMediaCapturePermissionFor 自动授权
  • 麦克风 / 摄像头 WebRTC getUserMedia():自动授权

下载拦截与存储

XWebViewView(
    config: XWebViewConfig(
        url: "https://example.com",
        downloadDestination: .userPick  // 弹出系统 Files 存储面板
    )
)
  • .sandbox:下载完成后弹出 UIActivityViewController(分享 / 存储到 Files
  • .userPick:下载完成后弹出 UIDocumentPickerViewController(直接选择存储位置)

H5 监听下载进度

// 下载进度0–100
window.addEventListener('__xwvDownloadProgress', (e) => {
    console.log(e.detail.url, e.detail.progress)
})

// 下载完成
window.addEventListener('__xwvDownloadDone', (e) => {
    if (e.detail.success) {
        console.log('下载成功', e.detail.url)
    } else {
        console.error('下载失败', e.detail.error)
    }
})

H5 ↔ Native 消息通信

// H5 → Native触发 onMessage 回调)
window.webkit.messageHandlers.ReactNativeWebView.postMessage(
    JSON.stringify({ type: 'login', token: '...' })
)
// Native → H5
XWebViewBridge.shared.currentController()?.postMessageToWeb(
    "window.dispatchEvent(new CustomEvent('nativeMsg', { detail: { key: 'value' } }))"
)

发版

SPM推荐

git add -A && git commit -m "release: 0.1.0"
git tag 0.1.0
git push origin main 0.1.0

Xcode 用户在 Package Dependencies 刷新即可获取新版本。

CocoaPods 私有 Spec

# 首次(只需一次)
pod repo add xuqm-specs https://xuqinmin.com/xuqinmin12/xuqm-specs.git

# 每次发版
pod spec lint XuqmSDK.podspec --allow-warnings
pod repo push xuqm-specs XuqmSDK.podspec --allow-warnings