启动期完成「ChannelConfig.plist 读 → SandboxPaths 算路径 →
gamehall.zip 解压」三步,lobbyIndex 真实存在于沙盒 Caches,
为 Phase 1.10 WebContainer file:// 加载就绪。
- 新增 ylgamehall/Source/Resource/ResourceUnzipper.swift
- public actor,全局单例 ResourceUnzipper.shared
- ensureReady() async throws:检查 lobbyVersionXML 不存在则调
FileManager.unzipItem (ZIPFoundation 扩展) 解压 Bundle 内
gamehall.zip 到 SandboxPaths.lobbyRoot
- UnzipError 类型化错误(bundleZipNotFound / unzipFailed)
- 幂等:已就绪直接 return,并发调用安全(actor 串行)
- 新增 ylgamehall/Resources/gamehall.zip:从 docs/res 拷一份入
Bundle(11.5 MB,2023-12 旧版;上线前由 H5 团队替换最新版,
ADR-002 已记录)
- Swift 6 严格并发适配:
- SandboxPaths:所有 static 成员标 nonisolated(无状态命名空间,
从 actor / 非 MainActor 上下文都能直接读 caches/documents/bundle
及 lobby 路径计算)
- BundleConfig:class 整体 nonisolated(Sendable + all-let 属性,
跨 actor 边界安全),允许 ResourceUnzipper actor 读 channel 配置
- RootViewController 补 ResourceUnzipper 烟雾测试 Task:
await ensureReady() 后打印耗时 + lobbyIndex 是否真实存在
- 真机验证(iOS Simulator):首次 1.266s 解压成功,二次启动 0s 跳过
71 lines
2.4 KiB
Swift
71 lines
2.4 KiB
Swift
//
|
||
// RootViewController.swift
|
||
// ylgamehall
|
||
//
|
||
// M0 阶段临时根控制器,后续将被 Coordinator + LobbyViewController 替换。
|
||
//
|
||
|
||
import UIKit
|
||
|
||
final class RootViewController: UIViewController {
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
view.backgroundColor = .black
|
||
|
||
// Phase 1.2 烟雾测试:打印 ChannelConfig.plist 的 11 项渠道注入值
|
||
let cfg = BundleConfig.shared
|
||
print("""
|
||
[BundleConfig] 渠道注入读取结果:
|
||
qiniuDomain = \(cfg.qiniuDomain)
|
||
gameId = \(cfg.gameId)
|
||
channel = \(cfg.channel)
|
||
gameDir = \(cfg.gameDir)
|
||
gameStart = \(cfg.gameStart)
|
||
gameConfig = \(cfg.gameConfig)
|
||
market = \(cfg.market)
|
||
agent = \(cfg.agent)
|
||
appVersion = \(cfg.appVersion)
|
||
other = "\(cfg.other)"
|
||
appleConfig = "\(cfg.appleConfig)"
|
||
""")
|
||
|
||
// Phase 1.3 烟雾测试:打印 SandboxPaths 计算路径
|
||
print("""
|
||
[SandboxPaths] 路径计算结果:
|
||
caches = \(SandboxPaths.caches.path)
|
||
documents = \(SandboxPaths.documents.path)
|
||
bundle = \(SandboxPaths.bundle.path)
|
||
lobbyRoot = \(SandboxPaths.lobbyRoot.path)
|
||
lobbyIndex = \(SandboxPaths.lobbyIndex.path)
|
||
lobbyVersionXML = \(SandboxPaths.lobbyVersionXML.path)
|
||
""")
|
||
|
||
// Phase 1.5 烟雾测试:触发 ResourceUnzipper,确认 lobby index.html 存在
|
||
Task {
|
||
let start = Date()
|
||
do {
|
||
try await ResourceUnzipper.shared.ensureReady()
|
||
let elapsed = Date().timeIntervalSince(start)
|
||
let exists = FileManager.default.fileExists(atPath: SandboxPaths.lobbyIndex.path)
|
||
print("""
|
||
[ResourceUnzipper] ensureReady 完成(耗时 \(String(format: "%.3f", elapsed))s)
|
||
lobbyIndex 存在: \(exists)
|
||
""")
|
||
} catch {
|
||
print("[ResourceUnzipper] ERROR: \(error)")
|
||
}
|
||
}
|
||
}
|
||
|
||
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||
.landscape
|
||
}
|
||
|
||
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
|
||
.landscapeRight
|
||
}
|
||
|
||
override var prefersStatusBarHidden: Bool { false }
|
||
}
|