From dcc12bb76dcdb3f95cc96ac815debcdcccf0dcde Mon Sep 17 00:00:00 2001 From: joywayer Date: Sun, 21 Jun 2026 23:47:23 +0800 Subject: [PATCH] =?UTF-8?q?Phase=201.2=EF=BC=9ABundleConfig=20=E8=AF=BB=20?= =?UTF-8?q?ChannelConfig.plist=20=E5=AE=8C=E6=88=90=2011=20=E9=A1=B9?= =?UTF-8?q?=E6=B8=A0=E9=81=93=E6=B3=A8=E5=85=A5=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 ylgamehall/Source/Resource/BundleConfig.swift - 11 个 public let 属性(qiniuDomain / gameId / channel / gameDir / gameStart / gameConfig / market / agent / appVersion / other / appleConfig) - public init(bundle: Bundle = .main) —— 默认走 main bundle,单测 可注入 mock bundle 验证不同 plist fixture - PropertyListSerialization 反序列化 ChannelConfig.plist - final class + Sendable(all-let,String 是 Sendable,Swift 6 严格并发下编译器静态校验通过) - 单例 BundleConfig.shared,业务统一通过此访问 - RootViewController.viewDidLoad 加烟雾测试 print 11 项值,首次运行 真机/模拟器即可在 console 验证读取正确 - BuildProject 通过,synchronized group 自动收编 BundleConfig.swift 为 source(.swift 文件类型走 SwiftCompile,不再卡 plist 那样的 resource 扁平化问题) - 单元测试待 Phase 0.2 单测 target 建立后补齐 --- ylgamehall/RootViewController.swift | 17 ++++++ ylgamehall/Source/Resource/BundleConfig.swift | 56 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 ylgamehall/Source/Resource/BundleConfig.swift diff --git a/ylgamehall/RootViewController.swift b/ylgamehall/RootViewController.swift index 879f67a..d2018e8 100644 --- a/ylgamehall/RootViewController.swift +++ b/ylgamehall/RootViewController.swift @@ -12,6 +12,23 @@ 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)" + """) } override var supportedInterfaceOrientations: UIInterfaceOrientationMask { diff --git a/ylgamehall/Source/Resource/BundleConfig.swift b/ylgamehall/Source/Resource/BundleConfig.swift new file mode 100644 index 0000000..903437b --- /dev/null +++ b/ylgamehall/Source/Resource/BundleConfig.swift @@ -0,0 +1,56 @@ +// +// BundleConfig.swift +// ylgamehall +// +// 渠道注入配置:从 Bundle 内的 ChannelConfig.plist 读 11 个 string 值。 +// 设计模式与契约见 docs/H5-Native-Implementation-Design.md §7 / ADR-007。 +// + +import Foundation + +/// 渠道注入配置(11 项),由 `BundleConfig.shared` 在 App 启动时一次性加载,运行期不变。 +/// +/// 多渠道分发:构建后用 `plutil` 修改 `.app/ChannelConfig.plist` + 重签, +/// 不需要重新 Xcode build。详见 ADR-007。 +public final class BundleConfig: Sendable { + + /// App 启动期默认读 main bundle 的 `ChannelConfig.plist`,业务代码统一通过此单例访问。 + public static let shared = BundleConfig() + + public let qiniuDomain: String + public let gameId: String + public let channel: String + public let gameDir: String + public let gameStart: String + public let gameConfig: String + public let market: String + public let agent: String + public let appVersion: String + public let other: String + public let appleConfig: String + + /// 单测可注入任意 bundle 验证不同 plist fixture。 + public init(bundle: Bundle = .main) { + let dict = Self.loadPlist(bundle: bundle) + qiniuDomain = dict["qiniudomain"] ?? "" + gameId = dict["gameid"] ?? "" + channel = dict["channel"] ?? "" + gameDir = dict["gamedir"] ?? "" + gameStart = dict["gamestart"] ?? "" + gameConfig = dict["gameconfig"] ?? "" + market = dict["market"] ?? "" + agent = dict["agent"] ?? "" + appVersion = dict["appversion"] ?? "" + other = dict["other"] ?? "" + appleConfig = dict["appleconfig"] ?? "" + } + + private static func loadPlist(bundle: Bundle) -> [String: String] { + guard let url = bundle.url(forResource: "ChannelConfig", withExtension: "plist"), + let data = try? Data(contentsOf: url), + let plist = try? PropertyListSerialization.propertyList( + from: data, format: nil) as? [String: String] + else { return [:] } + return plist + } +}