build-ipa/ironSource/PlayBTopOn/SERIAL_LOAD_LOGIC.md
2026-01-05 10:40:05 +08:00

315 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 串行加载广告逻辑说明
## 🔄 新的加载逻辑
### 之前的问题
- ❌ 一次性加载 3 个广告(并行)
- ❌ 浪费资源和流量
- ❌ 可能导致频率限制
- ❌ 定时器轮询检查是否可以展示
### 现在的改进
- ✅ 一个一个加载(串行)
- ✅ 加载失败 → 自动加载下一个
- ✅ 加载成功 → 立即展示
- ✅ 不需要定时器
- ✅ 节省资源和流量
## 📊 完整流程
### 场景 1: 第一个广告就成功
```
1. 初始化队列: [A, B, C]
2. 加载广告 A
↓ 加载成功 (ecpm 满足条件)
3. 自动展示广告 A ✓
4. 清空队列(不再加载 B 和 C
5. 用户关闭广告
6. 结束
```
### 场景 2: 第一个广告失败,第二个成功
```
1. 初始化队列: [A, B, C]
2. 加载广告 A
↓ 加载失败 ✗
3. 从队列取出下一个: B
4. 加载广告 B
↓ 加载成功 (ecpm 满足条件)
5. 自动展示广告 B ✓
6. 清空队列(不再加载 C
7. 用户关闭广告
8. 结束
```
### 场景 3: 广告 ecpm 不足
```
1. 初始化队列: [A, B, C]
2. 加载广告 A
↓ 加载成功,但 ecpm < 阈值 ✗
3. 从队列取出下一个: B
4. 加载广告 B
↓ 加载成功 (ecpm 满足条件)
5. 自动展示广告 B ✓
```
### 场景 4: 展示失败
```
1. 加载广告 A → 加载成功
2. 尝试展示 → didFailToDisplayAd
↓ "Cannot engage offer"
3. 触发 onAdClosed 回调
4. 检查队列是否还有广告
↓ 如果有
5. 1秒后加载下一个 (B)
6. 加载成功 → 自动展示 B ✓
```
### 场景 5: 所有广告都失败
```
1. 队列: [A, B, C]
2. 加载 A → 失败 → 加载 B → 失败 → 加载 C → 失败
3. 队列为空
4. 日志: "广告队列已空,所有广告都已尝试加载"
```
## 🔑 关键实现
### 1. 串行加载队列
```swift
// 广告 ID 队列
private var adIdQueue: [String] = []
// 当前正在加载的广告
private var currentLoadingAdId: String?
// 是否正在加载
private var isLoadingAd = false
```
### 2. 加载下一个广告
```swift
func loadNextAd() {
// 防止重复加载
if isLoadingAd { return }
// 队列为空,结束
if adIdQueue.isEmpty { return }
// 取出下一个
let nextAdId = adIdQueue.removeFirst()
isLoadingAd = true
// 开始加载
adItems[nextAdId]?.load()
}
```
### 3. 状态回调自动处理
```swift
adManager.onStatusChange = { id, st, ecpm in
if st == 2 {
// 加载完成 → 自动展示
self.autoShowLoadedAd(adId: id)
}
else if st == 5 {
// 加载失败 → 加载下一个
self.loadNextAd()
}
}
```
### 4. 自动展示逻辑
```swift
private func autoShowLoadedAd(adId: String) {
isLoadingAd = false
// 检查 ecpm
if ad.ecpm < adbrush_ecpm {
loadNextAd() // 不满足,加载下一个
return
}
// 展示广告
let showResult = ad.show(viewController) {
self.isshow = false
// 关闭后,如果队列还有广告,继续加载
if !self.adIdQueue.isEmpty {
self.loadNextAd()
}
}
if showResult {
self.isshow = true
adIdQueue.removeAll() // 成功后清空队列
} else {
loadNextAd() // 失败,加载下一个
}
}
```
## 📝 日志示例
### 正常流程
```
XS- 初始化广告队列: ["A", "B", "C"]
XS- 添加广告位: A
XS- 添加广告位: B
XS- 添加广告位: C
XS- 开始加载广告 [1/3]: A
XS- ad load ok: A ecpm:0.05
XS- 广告加载完成,准备自动展示: A
XS- 广告满足条件,准备展示: ecpm=0.05 >= 0.0005
XS- ✓ 广告展示成功
XS- ✓✓✓ didDisplayAd 回调被触发: A
XS- 开始上报 uploadAD_Show: A
```
### 第一个失败,加载第二个
```
XS- 开始加载广告 [1/3]: A
XS- load A err: timeout
XS- 广告加载失败,尝试加载下一个
XS- 开始加载广告 [2/3]: B
XS- ad load ok: B ecpm:0.05
XS- 广告加载完成,准备自动展示: B
XS- ✓ 广告展示成功
```
### ecpm 不足
```
XS- 开始加载广告 [1/3]: A
XS- ad load ok: A ecpm:0.0003
XS- 广告 ecpm 不足: 0.0003 < 0.0005,尝试下一个
XS- 开始加载广告 [2/3]: B
```
## 🎯 优势
| 对比项 | 旧逻辑(并行) | 新逻辑(串行) |
|-------|-------------|-------------|
| 加载方式 | 同时加载 3 个 | 一个一个加载 |
| 资源消耗 | 高 | 低 |
| 流量消耗 | 高 | 低 |
| 触发展示 | 定时器轮询 | 加载完立即展示 |
| 响应速度 | 慢(等待定时器) | 快(立即展示) |
| 成功率 | 低(频率限制) | 高(按需加载) |
| 失败处理 | 等待定时器重试 | 立即加载下一个 |
## ⚙️ 配置说明
### 不再需要的配置
以下代码已经不再起作用(保留是为了兼容性):
```swift
// YL_PlayVC.swift
DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
BbbAdManager.shared.start() // 不再需要
}
// bbbAdManager.swift
func start() {
// 新逻辑下不需要定时器
}
func showAd(v:UIViewController) {
// 新逻辑下由 autoShowLoadedAd 自动处理
}
```
### 新的流程
```swift
// YL_PlayVC.swift
BbbAdManager.shared.waitForSDKInitialization {
BbbAdManager.shared.loadAd(view: self)
// loadAd 会自动开始串行加载
// 加载完成后自动展示
// 不需要调用 start()
}
```
## 🔧 可选优化
### 1. 调整展示失败后的延迟
```swift
// 在 autoShowLoadedAd 的关闭回调中
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { // 可调整延迟时间
strongSelf.loadNextAd()
}
```
### 2. 添加最大重试次数
```swift
private var maxLoadAttempts = 3
private var currentAttempt = 0
func loadNextAd() {
if currentAttempt >= maxLoadAttempts {
NSLog("达到最大重试次数,停止加载")
return
}
currentAttempt += 1
// ... 继续加载
}
```
### 3. 记录失败原因
```swift
private var failedAds: [String: String] = [:] // adId -> error
// 在加载失败时记录
failedAds[adId] = error.localizedDescription
```
## ✅ 总结
新的串行加载逻辑:
- ✅ 更节省资源(按需加载)
- ✅ 响应更快(加载完立即展示)
- ✅ 成功率更高(避免频率限制)
- ✅ 逻辑更清晰(状态驱动)
- ✅ 日志更完整(每一步都有记录)
重新编译运行后,你会看到广告一个一个地加载和展示!
---
**修改时间:** 2025-01-04
**主要改进:** 并行 → 串行,定时器轮询 → 事件驱动
**向后兼容:** ✅ 保留了 start() 和 showAd() 方法