From b05899086256eecf0d304de4f53c2c7042f56e74 Mon Sep 17 00:00:00 2001 From: joywayer Date: Wed, 24 Jun 2026 02:12:21 +0800 Subject: [PATCH] =?UTF-8?q?3.F=20=E4=BF=AE=E5=A4=8D=EF=BC=9AmediaTypeAudio?= =?UTF-8?q?.user=20=E5=AD=97=E6=AE=B5=E5=85=BC=E5=AE=B9=20number=20?= =?UTF-8?q?=E4=B8=8E=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 问题 实测 H5 调 mediaTypeAudio 传入: {audiourl: "http://...amr", user: 0, type: 1} user 是 number(0),不是 string。我之前用 obj["user"]?.asString 严格 要求 string,导致解析失败 → silent return,远端语音无法播放。 ## 根因 daoqi 用 `[data objectForKey:@"user"]` 后 `[NSString stringWithFormat: @"%@", userid]` 容忍 NSNumber(ObjC `%@` 对 NSNumber 调 description 自动转 string)。新外壳走 Swift 强类型解析,丢了这个隐式兼容。 ## 修复 给 BridgeData 加 `asLooseString` 扩展: - string → 原样 - number → 整数样 double 转 Int 字符串(0.0 → "0"),其它走 String(d) - bool → "true"/"false" - null/array/object → nil mediaTypeAudio handler 把 `obj["user"]?.asString` 改为 `obj["user"]?.asLooseString`。`audiourl` 保持 asString(URL 永远是 string)。 `asLooseString` 也可供其它 H5 字段类型不严格的 handler 复用。 ## 验证 BuildProject 通过 0 错误。真机重试 mediaTypeAudio 应能正确解析 user=0 / user=12345 / user="abc" 等各种 H5 传入形态。 --- ylgamehall/Source/Bridge/BridgeProtocol.swift | 21 +++++++++++++++++++ .../Bridge/Handlers/RemoteAudioHandler.swift | 9 +++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/ylgamehall/Source/Bridge/BridgeProtocol.swift b/ylgamehall/Source/Bridge/BridgeProtocol.swift index 54f589b..3318f34 100644 --- a/ylgamehall/Source/Bridge/BridgeProtocol.swift +++ b/ylgamehall/Source/Bridge/BridgeProtocol.swift @@ -109,6 +109,27 @@ extension BridgeData { return nil } + /// 宽松字符串:string 保持原样、number 自动转 String、bool 转 "true"/"false"。 + /// + /// 用于 H5 字段类型不严格的场景(如 mediaTypeAudio.user 实际可能传 number + /// 0/1/userId 或 string)。对齐 daoqi `[NSString stringWithFormat:@"%@", + /// data[@"user"]]` 的容忍行为—— ObjC `%@` 对 NSNumber 调用 description 自动 + /// 转字符串。 + nonisolated public var asLooseString: String? { + switch self { + case .string(let s): return s + case .number(let d): + // 整数样的 double 转 Int 字符串(如 0.0 → "0",避免无意义的 .0 尾巴) + if d == d.rounded(), d.isFinite, abs(d) < Double(Int.max) { + return String(Int(d)) + } + return String(d) + case .bool(let b): return b ? "true" : "false" + case .null: return nil + case .array, .object: return nil + } + } + nonisolated public var asDouble: Double? { if case .number(let d) = self { return d } return nil diff --git a/ylgamehall/Source/Bridge/Handlers/RemoteAudioHandler.swift b/ylgamehall/Source/Bridge/Handlers/RemoteAudioHandler.swift index 2f2f50c..e2c788f 100644 --- a/ylgamehall/Source/Bridge/Handlers/RemoteAudioHandler.swift +++ b/ylgamehall/Source/Bridge/Handlers/RemoteAudioHandler.swift @@ -247,11 +247,14 @@ public enum RemoteAudioHandler { bridge: any BridgeProtocol, callback: BridgeCallback? ) async { - // 1. 解析入参(只有 audiourl + user 两个字段,对齐 daoqi - // NewRootVC.m:326-328 / gameController.m:435-437) + // 1. 解析入参(核心字段 audiourl + user,对齐 daoqi NewRootVC.m:326-328 / + // gameController.m:435-437;H5 实测也会带 type 字段但 daoqi 注释掉、不用)。 + // + // ⚠️ user 字段在 H5 实测中是 number(如 0、12345),不是 string;用 + // asLooseString 兼容两种类型(对齐 daoqi `%@` 格式化容忍 NSNumber 行为) guard let obj = data?.asObject, let urlString = obj["audiourl"]?.asString, - let user = obj["user"]?.asString, + let user = obj["user"]?.asLooseString, let downloadURL = URL(string: urlString) else { log.error("mediaTypeAudio: bad params \(String(describing: data), privacy: .public)")