Files
youle_app_ios_v2/ylgamehall/Source/Resource/SandboxPaths.swift
T
joywayerandClaude Opus 4.7 04e702a99b Phase 1.F: WebView 加载从 file:// 迁到 ylgame://h5 自定义 scheme
为未来 Cocos 子游戏 H5 build 适配铺路(file:// 下 Cocos XHR/fetch 受
null-origin 限制几乎必踩坑),同时保留大厅 + 子游戏跨页 localStorage
共享语义(用单虚拟 host `h5` 让所有 H5 same-origin)。

变更:
- 新增 AppSchemeHandler(WKURLSchemeHandler 单例 + Range/MIME/异步 IO/
  取消语义;闭包只携 Sendable ObjectIdentifier,不捕获 task)
- SandboxPaths 加 lobbyIndexAppURL / subGameIndexAppURL builders
- BridgedWebView 注册 scheme handler(WKWebView init 前)
- WebContainerViewController / SubGameViewController 的 loadFileURL
  → webView.load(URLRequest),OverlayViewController 不变

文档:
- Plan 新增 Phase 1.F (1.18-1.21) + ADR-010 决策记录 + 进度勾选
- Design 新增 §7.6 包含 URL 结构 / 实现要点 / 等价性表 / Cocos 预检脚本
- Contract §0.2 / §4.1 / §10 验收清单同步切换说明(H5 可观察差异:
  location.protocol "file:" → "ylgame:",项目方已 grep 确认现网 H5
  不依赖此字面)

存量影响:file:// → ylgame:// origin 切换时老用户 localStorage 一次性
清零,已与项目方确认业务可接受、不做迁移补偿。

BuildProject 通过。Plan 进度已勾选 1.18/1.19/1.20。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-29 08:58:00 +08:00

98 lines
3.7 KiB
Swift
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.
//
// SandboxPaths.swift
// ylgamehall
//
// 集中管理沙盒与 Bundle 路径,避免散落 NSSearchPathFor...。
// 详见 docs/H5-Native-Implementation-Design.md §7.1。
//
import Foundation
/// 沙盒、Bundle、H5 资源路径的统一入口。所有 ResourceUnzipper / WebView 加载
/// 等模块通过此命名空间获取路径,禁止重新写 `urls(for:in:)` 等散落调用。
public enum SandboxPaths {
// MARK: - 基础沙盒目录
/// `Library/Caches/`(系统空间不足时可能被清,需可重建)
nonisolated public static var caches: URL {
FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
}
/// `Documents/`(用户级持久化,iCloud 备份)
nonisolated public static var documents: URL {
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
}
/// `<App>.app/`
nonisolated public static var bundle: URL {
Bundle.main.bundleURL
}
// MARK: - 大厅 H5 路径(基于 BundleConfig.shared 的当前渠道)
/// 大厅 H5 解压根目录:`{Caches}/{gamedir}/`
nonisolated public static var lobbyRoot: URL {
caches.appendingPathComponent(BundleConfig.shared.gameDir)
}
/// 大厅 H5 入口 HTML`{Caches}/{gamedir}/{gamestart}/index.html`
nonisolated public static var lobbyIndex: URL {
let cfg = BundleConfig.shared
return caches
.appendingPathComponent(cfg.gameDir)
.appendingPathComponent(cfg.gameStart)
.appendingPathComponent("index.html")
}
/// 大厅 H5 版本标记文件:`{Caches}/{gamedir}/{gamestart}/version.xml`
/// 由 ResourceUnzipper 判断是否需要解压初始 gamehall.zip。
nonisolated public static var lobbyVersionXML: URL {
let cfg = BundleConfig.shared
return caches
.appendingPathComponent(cfg.gameDir)
.appendingPathComponent(cfg.gameStart)
.appendingPathComponent("version.xml")
}
// MARK: - 子游戏 H5 路径(参数化,由 SwitchOverGameData 传入)
/// 子游戏 H5 解压根目录:`{Caches}/{dir}/`
nonisolated public static func subGameRoot(_ dir: String) -> URL {
caches.appendingPathComponent(dir)
}
/// 子游戏 H5 入口 HTML`{Caches}/{dir}/{start}/index.html`
nonisolated public static func subGameIndex(_ dir: String, _ start: String) -> URL {
caches.appendingPathComponent(dir)
.appendingPathComponent(start)
.appendingPathComponent("index.html")
}
// MARK: - App scheme URLPhase 1.F WKURLSchemeHandler 迁移)
//
// 由 AppSchemeHandler 接管的自定义 scheme URL。大厅 + 所有子游戏共用
// 同一虚拟 host (`ylgame://h5`),从而 same-origin → 共享 localStorage。
// 路径前缀区分目标 (`lobby` / `subgame/<dir>`)handler 内反向映射回
// 上面 lobbyRoot / subGameRoot(_:) 的沙盒物理路径。
/// 大厅 H5 入口的 app:// URL`ylgame://h5/lobby/<gameStart>/index.html`
nonisolated public static var lobbyIndexAppURL: URL {
var c = URLComponents()
c.scheme = AppScheme.scheme
c.host = AppScheme.host
c.path = "/\(AppScheme.lobbyPrefix)/\(BundleConfig.shared.gameStart)/index.html"
// 字面下 path 不含空格 / 中文,force-unwrap 安全
return c.url!
}
/// 子游戏 H5 入口的 app:// URL`ylgame://h5/subgame/<dir>/<start>/index.html`
nonisolated public static func subGameIndexAppURL(_ dir: String, _ start: String) -> URL {
var c = URLComponents()
c.scheme = AppScheme.scheme
c.host = AppScheme.host
c.path = "/\(AppScheme.subGamePrefix)/\(dir)/\(start)/index.html"
return c.url!
}
}