// // DeviceInfoHandler.swift // ylgamehall // // H5 → Native handler:getphoneInfo + 反向 callback getphoneinfo(小写 i) // 契约:docs/H5-Native-Contract.md §3.1 [21] + §3.2 [1] + 表 A // // ⚠️ 大小写硬约束: // H5 调用:bridge.callHandler("getphoneInfo", ...) 大写 I // 原生回调:bridge.callHandler("getphoneinfo", ...) 小写 i // import UIKit @MainActor public enum DeviceInfoHandler { public static func register(on bridge: any BridgeProtocol) { // 【21】getphoneInfo(大写 I) // 入参忽略;cb:"getphoneInfo" // 反向调用:bridge.call("getphoneinfo"(小写 i!),data: 表 A 6 字段) bridge.register("getphoneInfo") { [weak bridge] _, callback in callback?(.string("getphoneInfo")) Task { @MainActor in let snapshot = DeviceInfoSnapshot.current() bridge?.call("getphoneinfo", // ⚠️ 小写 i data: .object(snapshot.bridgeFields), callback: nil) } } } } /// 设备信息快照(契约 §3.2 表 A 6 字段,全部 string)。 @MainActor public struct DeviceInfoSnapshot { public let phoneAdresseMAC: String // UIDevice.identifierForVendor.uuidString public let phoneDeviceBrand: String // "iPhone" / "iPad" public let phoneIMEI: String // 历史用 IDFA;新外壳暂用 idfv(IDFA 需 ATT,本项目不接) public let phoneModel: String // UIDevice.localizedModel public let phoneProvidersName: String // 运营商名(iOS 16+ 私有 / 已弃用,暂空) public let phoneVersion: String // UIDevice.systemVersion public static func current() -> DeviceInfoSnapshot { let device = UIDevice.current let idfv = device.identifierForVendor?.uuidString ?? "" return DeviceInfoSnapshot( phoneAdresseMAC: idfv, phoneDeviceBrand: device.model, phoneIMEI: idfv, // CLAUDE.md 不接 ATT/IDFA,沿用 idfv phoneModel: device.localizedModel, phoneProvidersName: "", // iOS 16+ CTCarrier 已弃用,业务暂用不到 phoneVersion: device.systemVersion ) } /// 契约 §3.2 表 A 字段名严格保持 public var bridgeFields: [String: BridgeData] { [ "PhoneAdresseMAC": .string(phoneAdresseMAC), "PhoneDeviceBrand": .string(phoneDeviceBrand), "PhoneIMEI": .string(phoneIMEI), "PhoneModel": .string(phoneModel), "PhoneProvidersName": .string(phoneProvidersName), "PhoneVersion": .string(phoneVersion) ] } }