Files
real-e-party-iOS/SDK_MANAGER_IMPLEMENTATION.md
edwinQQQ 7626eb8351 feat: 添加动态发布功能及相关文档
主要变更:
1. 新增 EPImageUploader.swift 和 EPProgressHUD.swift,提供图片批量上传和进度显示功能。
2. 新建 EPMomentAPISwiftHelper.swift,封装动态 API 的 Swift 版本。
3. 更新 EPMomentPublishViewController,集成新上传功能并实现发布成功通知。
4. 创建多个文档,包括实施报告、检查清单和快速使用指南,详细记录功能实现和使用方法。
5. 更新 Bridging Header,确保 Swift 和 Objective-C 代码的互操作性。

此功能旨在提升用户体验,简化动态发布流程,并提供清晰的文档支持。
2025-10-11 17:16:30 +08:00

11 KiB
Raw Blame History

SDK 管理器实施总结

实施时间

2025-10-11

问题背景

崩溃原因

Terminating app due to uncaught exception 'com.tencent.qcloud.error', 
reason: '您没有配置默认的OCR服务配置请配置之后再调用该方法'

根本原因

  • EPImageUploader 直接调用 UploadFile.qCloudUploadImage()
  • UploadFilefileModel 属性为 nil未初始化
  • QCloud SDK 需要先调用 initQCloud 获取配置才能使用

解决方案

架构设计

创建独立的 SDK 管理器,职责分离:

EPSDKManager (SDK 管理)
  ↓ 提供配置
EPImageUploader (业务逻辑)
  ↓ 调用底层
UploadFile (基础设施)

设计决策

  1. 初始化时机: 懒加载(首次上传时自动初始化)
  2. Token 刷新: 过期后重新获取
  3. 错误处理: 直接返回失败,不重试
  4. 旧代码兼容: 保持 UploadFile.m 不变

实施内容

1. EPQCloudConfig.swift (60 行)

路径: YuMi/E-P/Common/EPQCloudConfig.swift

功能:

  • QCloud 配置数据模型
  • 从 API 返回数据初始化
  • 提供过期检查

核心字段:

struct EPQCloudConfig {
    let secretId: String
    let secretKey: String
    let sessionToken: String
    let bucket: String
    let region: String
    let customDomain: String
    let startTime: Int64
    let expireTime: Int64
    let appId: String
    let accelerate: Int
    
    var isExpired: Bool  // 检查是否过期
}

2. EPSDKManager.swift (116 行)

路径: YuMi/E-P/Common/EPSDKManager.swift

功能:

  • 单例模式管理所有第三方 SDK
  • QCloud 初始化和配置缓存
  • 并发安全的初始化控制

核心方法:

@objc class EPSDKManager: NSObject {
    @objc static let shared: EPSDKManager
    
    // 检查 QCloud 是否就绪
    @objc func isQCloudReady() -> Bool
    
    // 确保 QCloud 就绪(自动初始化)
    @objc func ensureQCloudReady(completion: (Bool, String?) -> Void)
    
    // 主动初始化 QCloud
    @objc func initializeQCloud(completion: (Bool, String?) -> Void)
}

关键特性:

  • 回调队列: 处理并发初始化请求
  • NSLock 保护: 线程安全
  • 配置缓存: 避免重复获取 Token
  • 过期检查: 自动重新初始化

初始化流程:

1. 检查是否正在初始化 → 是:加入回调队列
2. 检查是否已初始化且未过期 → 是:直接返回成功
3. 调用 Api.getQCloudInfo 获取 Token
4. 保存 EPQCloudConfig
5. 调用 UploadFile.initQCloud()(兼容性)
6. 延迟 0.3s 确保初始化完成
7. 触发所有回调

3. EPImageUploader.swift修改

路径: YuMi/E-P/Common/EPImageUploader.swift

修改内容:

  • 提取 performBatchUpload 私有方法(原上传逻辑)
  • uploadImages 中添加初始化检查

修改前:

@objc func uploadImages(...) {
    // 直接上传
    UploadFile.share().qCloudUploadImage(...)
}

修改后:

@objc func uploadImages(...) {
    // 1. 确保 QCloud 已初始化
    EPSDKManager.shared.ensureQCloudReady { isReady, errorMsg in
        if !isReady {
            failure(errorMsg ?? "QCloud 初始化失败")
            return
        }
        
        // 2. 执行上传
        self.performBatchUpload(...)
    }
}

private func performBatchUpload(...) {
    // 原有的并发上传逻辑
}

4. Bridging Header修改

文件: YuMi/YuMi-Bridging-Header.h

新增:

#import "Api+Mine.h"  // 用于调用 getQCloudInfo

执行流程

首次上传流程

用户点击发布
  ↓
EPMomentPublishViewController.onPublish()
  ↓
EPImageUploader.uploadImages()
  ↓
EPSDKManager.ensureQCloudReady()
  ↓
检查 isQCloudReady() → false (未初始化)
  ↓
initializeQCloud()
  ↓
调用 Api.getQCloudInfo
  ↓ (GET: tencent/cos/getToken)
返回 Token 数据
  ↓
保存到 EPQCloudConfig
  ↓
调用 UploadFile.share().initQCloud() (兼容)
  ↓
延迟 0.3s 等待初始化完成
  ↓
回调成功 → performBatchUpload()
  ↓
并发上传图片(最多 3 张同时)
  ↓
显示进度 "上传中 X/Y"
  ↓
全部完成 → 调用发布 API
  ↓
发布成功 → Dismiss 页面

后续上传流程

EPSDKManager.ensureQCloudReady()
  ↓
检查 isQCloudReady() → true (已初始化且未过期)
  ↓
直接回调成功 → 立即执行 performBatchUpload()

Token 过期流程

EPSDKManager.ensureQCloudReady()
  ↓
检查 config.isExpired → true (已过期)
  ↓
自动调用 initializeQCloud() 重新获取
  ↓
继续上传流程

技术亮点

1. 懒加载策略

  • 首次使用时才初始化
  • 节省 App 启动时间
  • 按需加载,资源利用最优

2. 并发安全设计

private var isQCloudInitializing = false
private var qcloudInitCallbacks: [(Bool, String?) -> Void] = []
private let lock = NSLock()
  • NSLock 保护共享状态
  • 回调队列处理并发请求
  • 避免重复初始化

3. 自动过期重新初始化

var isExpired: Bool {
    return Date().timeIntervalSince1970 > Double(expireTime)
}
  • 检查 Token 是否过期
  • 过期自动重新获取
  • 无需手动管理

4. 向后兼容

// 继续调用旧的初始化方法
UploadFile.share().initQCloud()
  • 新旧代码可以并存
  • 旧代码依然可以正常工作
  • 平滑过渡,降低风险

代码统计

新建文件

文件 行数 说明
EPQCloudConfig.swift 60 QCloud 配置 Model
EPSDKManager.swift 116 SDK 管理器
合计 176 纯 Swift

修改文件

文件 修改行数 说明
EPImageUploader.swift +30 添加初始化检查
YuMi-Bridging-Header.h +1 新增 Api+Mine.h
合计 +31 配置更新

总计

  • 新增: 176 行 Swift 代码
  • 修改: 31 行代码
  • 不改: UploadFile.m (410 行保持不变)

文件清单

新建

  • YuMi/E-P/Common/EPQCloudConfig.swift
  • YuMi/E-P/Common/EPSDKManager.swift

修改

  • YuMi/E-P/Common/EPImageUploader.swift
  • YuMi/YuMi-Bridging-Header.h

不改

  • YuMi/Tools/File/UploadFile.m
  • YuMi/Tools/File/UploadFile.h

测试计划

功能测试

ID 测试用例 预期结果
T01 冷启动后首次上传单图 自动初始化 QCloud → 上传成功
T02 连续上传多次 复用配置,无重复初始化
T03 并发初始化(快速点击两次发布) 第二次请求加入回调队列,共享初始化结果
T04 网络异常初始化失败 显示错误提示,不崩溃
T05 Token 模拟过期 自动重新获取配置

测试步骤

T01: 冷启动首次上传

1. 杀掉 App
2. 重新启动
3. 进入发布页面
4. 选择 1 张图片
5. 点击发布
6. 观察:
   - 短暂等待(初始化)
   - 显示 "上传中 1/1"
   - 发布成功

T02: 连续上传

1. 上传成功后
2. 再次进入发布页面
3. 选择图片并发布
4. 观察:
   - 无等待(配置已缓存)
   - 立即开始上传

T03: 并发初始化

1. 冷启动
2. 准备两个发布操作
3. 快速连续点击发布
4. 观察:
   - 两个请求都成功
   - 只初始化一次

T04: 网络异常

1. 断开网络
2. 冷启动
3. 尝试上传
4. 观察:
   - 显示错误提示
   - App 不崩溃

T05: Token 过期测试

1. 在 EPSDKManager 中临时修改过期判断:
   return true  // 强制过期
2. 尝试上传
3. 观察:
   - 自动重新初始化
   - 上传成功

监控要点

日志输出

建议在关键节点添加日志:

// EPSDKManager.swift
print("[EPSDKManager] QCloud 初始化开始")
print("[EPSDKManager] QCloud 配置获取成功,过期时间: \(config.expireTime)")
print("[EPSDKManager] QCloud 初始化完成")

// EPImageUploader.swift
print("[EPImageUploader] 等待 QCloud 初始化...")
print("[EPImageUploader] QCloud 就绪,开始上传 \(images.count) 张图片")
print("[EPImageUploader] 上传进度: \(uploaded)/\(total)")

性能指标

指标 目标值 说明
初始化时间 < 1s 首次获取 QCloud Token
单图上传 < 3s 1MB 图片
9 图上传 < 15s 并发 3 张
配置复用 0s 已初始化时无等待

架构优势

1. 职责分离

组件 职责 依赖
EPSDKManager SDK 初始化管理、配置缓存 Api+Mine
EPImageUploader 图片上传业务逻辑 EPSDKManager
UploadFile QCloud 底层上传 QCloudCOSXML

2. 技术特点

  • 自动初始化: 用户无感知,首次使用时自动触发
  • 并发控制: 回调队列 + NSLock 确保线程安全
  • Token 管理: 自动检查过期,按需刷新
  • 扩展性强: 未来其他 SDK 可接入同一管理器

3. 向后兼容

// 新代码调用 EPSDKManager
EPSDKManager.shared.ensureQCloudReady { ... }

// 旧代码依然可以直接调用
UploadFile.share().initQCloud()

API 接口

调用的 API

接口: GET tencent/cos/getToken

返回数据:

{
  "code": 200,
  "data": {
    "secretId": "xxx",
    "secretKey": "xxx",
    "sessionToken": "xxx",
    "bucket": "xxx",
    "region": "xxx",
    "customDomain": "https://xxx",
    "startTime": 1728123456,
    "expireTime": 1728209856,
    "appId": "xxx",
    "accelerate": 1
  }
}

已知问题

当前

潜在风险

  1. 初始化延迟 0.3s:

    • 当前使用固定延迟等待 UploadFile 初始化
    • 可能在慢速设备上不够
    • 可优化为轮询检查或使用通知
  2. Token 提前过期:

    • 当前在过期时才重新获取
    • 可优化为提前 5 分钟主动刷新

未来优化

短期(本周)

  • 添加初始化日志,便于调试
  • 测试所有场景
  • 验证 Token 过期处理

中期(本月)

  • 优化初始化完成检测机制(替代固定延迟)
  • 添加 Token 提前刷新策略
  • 接入其他 SDKIM、推送等

长期(季度)

  • 统一 SDK 初始化入口
  • 添加 SDK 状态监控
  • 实现配置本地持久化

相关文档

Git 状态

新建文件:
  YuMi/E-P/Common/EPQCloudConfig.swift
  YuMi/E-P/Common/EPSDKManager.swift

修改文件:
  YuMi/E-P/Common/EPImageUploader.swift
  YuMi/YuMi-Bridging-Header.h

编译状态

  • Swift 语法检查: 无错误
  • Bridging Header: 依赖链问题已解决
  • OC/Swift 互操作: 正确配置

下一步

  1. 在 Xcode 中添加新文件到项目
  2. Clean Build (Shift+Cmd+K)
  3. Build (Cmd+B)
  4. 运行并测试上传功能

实施状态: 代码完成,待测试验证
实施者: AI Assistant (Linus Mode)
审查状态: 待审查