214 lines
6.6 KiB
Markdown
214 lines
6.6 KiB
Markdown
# iOS 12/13 兼容性修复总结
|
||
|
||
## 修复时间
|
||
2025-01-01
|
||
|
||
## 问题描述
|
||
应用在 iOS 12/13 系统上启动时崩溃,原因:
|
||
1. 使用了 `Task { await ... }` 等 Swift Concurrency API(需要 iOS 15+)
|
||
2. 无条件导入 `AppTrackingTransparency` 框架(仅 iOS 14+ 可用)
|
||
|
||
## 已修复的文件
|
||
|
||
### 1. PlayBTopOn/AppDelegate.swift
|
||
**修改内容:**
|
||
- ❌ 移除:`Task { await BbbAdManager.shared.initAd() }`
|
||
- ✅ 替换为:`DispatchQueue.global(qos: .userInitiated).async { BbbAdManager.shared.initAd() }`
|
||
|
||
**影响:** 兼容 iOS 12+,使用传统的 GCD 异步方式
|
||
|
||
### 2. PlayBTopOn/playB/YL_PlayVC.swift
|
||
**修改内容:**
|
||
- ❌ 移除:`Task { await BbbAdManager.shared.waitForSDKInitialization() ... }`
|
||
- ✅ 替换为:`BbbAdManager.shared.waitForSDKInitialization { BbbAdManager.shared.loadAd(view: self) }`
|
||
|
||
**影响:** 使用回调方式等待 SDK 初始化完成
|
||
|
||
### 3. PlayBTopOn/playB/bbbAdManager.swift
|
||
**修改内容:**
|
||
- ✅ 新增:`initAd(completion:)` - 基于回调的初始化方法(兼容所有版本)
|
||
- ✅ 新增:`waitForSDKInitialization(completion:)` - 基于回调的等待方法
|
||
- ✅ 重命名:原 `initAd() async` → `initAdAsync()` 并标记 `@available(iOS 15.0, *)`
|
||
- ✅ 重命名:原 `waitForSDKInitialization() async` → `waitForSDKInitializationAsync()` 并标记 `@available(iOS 15.0, *)`
|
||
- 🔴 **关键修复:** 移除 `CheckedContinuation` 类型,改用普通闭包数组
|
||
- ❌ `private var initializationContinuations: [CheckedContinuation<Void, Never>] = []`
|
||
- ✅ `private var initializationCallbacks: [() -> Void] = []`
|
||
|
||
**影响:** 提供双版本 API,默认使用回调方式,移除了导致 iOS 12 崩溃的 Swift Concurrency 类型
|
||
|
||
### 4. PlayBTopOn/playB/idfa.swift
|
||
**修改内容:**
|
||
- ❌ 移除:顶部的 `import AppTrackingTransparency`
|
||
- ✅ 添加:`#if canImport(AppTrackingTransparency) import AppTrackingTransparency #endif`
|
||
- ✅ 添加:所有 ATT 相关代码都用 `#if canImport(AppTrackingTransparency)` 包裹
|
||
- ✅ 修改:`checkATT()` 方法使用条件编译,低版本自动降级到旧 API
|
||
|
||
**影响:** 编译时只在支持的平台引入 ATT,运行时自动选择合适的 IDFA 获取方式
|
||
|
||
### 5. PlayBTopOn/playB/YL_NetWorkManager.swift
|
||
**修改内容:**
|
||
- ❌ 移除:顶部的 `import AppTrackingTransparency`
|
||
- ✅ 添加:`#if canImport(AppTrackingTransparency) import AppTrackingTransparency #endif`
|
||
- ✅ 修改:`getAdvertisingTrackingStatus()` 使用条件编译
|
||
- ✅ 修改:`isAdvertisingTrackingEnabled()` 使用条件编译
|
||
|
||
**影响:** ATT API 调用被条件编译保护,低版本使用 `ASIdentifierManager` 旧 API
|
||
|
||
## 新增文件
|
||
|
||
### 1. iOS12_COMPATIBILITY_GUIDE.md
|
||
详细的配置指南,包括:
|
||
- 问题说明
|
||
- Xcode 配置步骤
|
||
- 测试验证方法
|
||
- 常见问题解答
|
||
|
||
### 2. check_ios12_compatibility.sh
|
||
自动化检查脚本,检测:
|
||
- Task/async/await 未保护的使用
|
||
- AppTrackingTransparency 导入保护
|
||
- Podfile 和项目配置
|
||
- 其他潜在问题
|
||
|
||
### 3. CHANGES_SUMMARY.md
|
||
本文件,记录所有修改内容
|
||
|
||
## 验证结果
|
||
|
||
✅ **所有代码检查通过!**
|
||
|
||
```
|
||
======================================
|
||
iOS 12/13 兼容性检查
|
||
======================================
|
||
|
||
✓ 未发现 Task 调用
|
||
✓ 所有 async 函数都已保护
|
||
✓ AppTrackingTransparency 导入已正确保护
|
||
✓ Podfile 最低版本: iOS 12.0
|
||
✓ 找到 Info.plist
|
||
|
||
错误: 0
|
||
警告: 3
|
||
```
|
||
|
||
## 🔴 关键崩溃修复
|
||
|
||
**问题:** 应用在打印 `"XS- 开始创建 BbbAdManager.shared 单例"` 后崩溃
|
||
|
||
**原因:** `CheckedContinuation` 类型在 iOS 12 上不存在
|
||
|
||
**解决:** 已替换为普通闭包数组
|
||
|
||
详细信息请查看:[CRITICAL_FIX.md](./CRITICAL_FIX.md)
|
||
|
||
## 仍需手动操作的事项
|
||
|
||
### ⚠️ 重要:在 Xcode 中配置弱链接
|
||
|
||
1. **打开 Xcode 项目**
|
||
```
|
||
open PlayBTopOn.xcworkspace
|
||
```
|
||
|
||
2. **配置 AppTrackingTransparency 为 Optional**
|
||
- 选择项目 → TARGETS → PlayBTopOn
|
||
- Build Phases → Link Binary With Libraries
|
||
- 找到或添加 `AppTrackingTransparency.framework`
|
||
- 将 Status 改为 **Optional** (不是 Required)
|
||
|
||
3. **验证 Deployment Target**
|
||
- General → Deployment Info
|
||
- iOS Deployment Target 设置为 **12.0**
|
||
|
||
### 可选:添加 ATT 权限说明
|
||
|
||
如果需要在 iOS 14+ 上请求追踪权限,在 `Info.plist` 中添加:
|
||
|
||
```xml
|
||
<key>NSUserTrackingUsageDescription</key>
|
||
<string>我们需要获取您的广告标识符以提供个性化广告体验</string>
|
||
```
|
||
|
||
## 兼容性矩阵
|
||
|
||
| iOS 版本 | 支持状态 | IDFA 获取方式 | 异步调用方式 |
|
||
|---------|---------|-------------|------------|
|
||
| iOS 12.x | ✅ 完全支持 | ASIdentifierManager | DispatchQueue + 回调 |
|
||
| iOS 13.x | ✅ 完全支持 | ASIdentifierManager | DispatchQueue + 回调 |
|
||
| iOS 14.x | ✅ 完全支持 | ATTrackingManager | DispatchQueue + 回调 |
|
||
| iOS 15+ | ✅ 完全支持 | ATTrackingManager | async/await 或 回调 |
|
||
|
||
## 测试建议
|
||
|
||
### 1. 编译测试
|
||
```bash
|
||
# 清理构建
|
||
xcodebuild clean
|
||
|
||
# 构建项目
|
||
xcodebuild build -workspace PlayBTopOn.xcworkspace \
|
||
-scheme PlayBTopOn \
|
||
-destination 'platform=iOS Simulator,name=iPhone 8,OS=12.4'
|
||
```
|
||
|
||
### 2. 模拟器测试
|
||
- iOS 12.4 (iPhone 8)
|
||
- iOS 13.7 (iPhone 11)
|
||
- iOS 14.8 (iPhone 12)
|
||
- iOS 15.0+ (任意设备)
|
||
|
||
### 3. 真机测试
|
||
在实际设备上测试,特别是:
|
||
- 旧设备运行 iOS 12/13
|
||
- 新设备运行 iOS 14+
|
||
|
||
## 回滚方法
|
||
|
||
如果需要回滚这些更改:
|
||
|
||
```bash
|
||
git log --oneline # 查看提交历史
|
||
git revert <commit-hash> # 回滚指定提交
|
||
```
|
||
|
||
或者从备份恢复:
|
||
```bash
|
||
cp -r PlayBTopOn.backup/* PlayBTopOn/
|
||
```
|
||
|
||
## 技术要点总结
|
||
|
||
### Swift Concurrency 兼容性
|
||
- `Task` / `async` / `await` 需要 iOS 15+
|
||
- 使用 `@available(iOS 15.0, *)` 标记
|
||
- 提供基于 `DispatchQueue` 和回调的替代方案
|
||
|
||
### 弱链接 (Weak Linking)
|
||
- 框架在 Build Phases 中设置为 Optional
|
||
- 运行时动态加载,不存在也不崩溃
|
||
- 代码中用 `#if canImport()` 条件编译
|
||
|
||
### 版本检查
|
||
- `@available(iOS 14, *)` - 运行时检查
|
||
- `#if canImport()` - 编译时检查
|
||
- 两者结合使用最安全
|
||
|
||
## 相关文档
|
||
|
||
- [iOS12_COMPATIBILITY_GUIDE.md](./iOS12_COMPATIBILITY_GUIDE.md) - 详细配置指南
|
||
- [check_ios12_compatibility.sh](./check_ios12_compatibility.sh) - 自动检查脚本
|
||
|
||
## 联系支持
|
||
|
||
如遇问题,请:
|
||
1. 运行 `./check_ios12_compatibility.sh` 检查配置
|
||
2. 查看 Xcode 控制台的崩溃日志
|
||
3. 确认 AppTrackingTransparency 已设置为 Optional
|
||
|
||
---
|
||
|
||
**修复完成 ✅**
|
||
**最低支持版本:iOS 12.0**
|
||
**测试状态:代码验证通过,待真机测试**
|