Files
youle_app_ios_v2/ylgamehall/Source/Bridge/Handlers/StartLocationHandler.swift
T
joywayerandClaude Opus 5 3f8b382ad3 加桥/定位边界诊断日志,排查子游戏收不到 getlocationinfo
现象:大厅 H5 能正确拿到定位,子游戏拿不到。已静态排除「子游戏未注册
handler」与「回调错发给大厅」两个猜测(BridgeBus 是 per-WebView 实例、
handlers 是实例状态,反向 call 捕获各自的 bridge,物理上不可能串台;
下载真实子游戏 zip 比对后确认 H5 侧大厅/子游戏逻辑完全对称)。

为定位真正的失败层,在各组件边界加日志(纯诊断,不改任何行为):
- BridgeBus 加 label(lobby / subGame)区分来源,记录 ← H5 调用、
  → H5 反向 call、native handler 未注册、evaluateJavaScript 失败
- sendToJS 改为返回 'ok'/'no-bridge',H5 侧 bridge 未就绪导致的静默丢包
  现在会打错误日志(原实现 `if (window.X)` 直接丢弃,完全不可见)
- LocationService 记录 requestOnce 序号 / shared manager id /
  requestLocation 的 BOOL 返回值 / completionBlock 是否回来 / stop() 调用
  —— 高德文档明确 requestLocation 返回 NO 时 completionBlock 永不调用,
  当前代码忽略该返回值会让 continuation 永挂,H5 连 errorCode 12 都收不到
- H5ErrorRelay 补 console.warn 中继,让 WVJB「H5 侧无对应 handler」的
  warn 能出现在 Xcode console

契约影响:无。仅新增日志与可选 label 参数,桥接接口名 / 字段名 / 数据结构
均未变动(docs/H5-Native-Contract.md §3.1[20]/ §3.2[6]不变)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UMPCLfsuxvwgMotzsb67QH
2026-08-07 01:54:18 +08:00

74 lines
4.0 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.
//
// StartLocationHandler.swift
// ylgamehall
//
// H5 → Native handlerstartlocation — 定位(Phase 5 接入高德 SDK 后激活真实路径)
// 契约:docs/H5-Native-Contract.md §3.1 20 + §3.2 6
//
// 完整链路:
// 1. LocationService.shared.requestOnce()actor,包 AMapLocationManager 异步)
// 2. bridge.call("getlocationinfo", 9 字段) 反向 callback
// - latitude / longitude 是 **string**`String(format: "%f")`
// - province 小写 p(与 sharelogin.Province 大写不同)
// 3. 失败 → getlocationinfo({errorCode:12, errorMsg:"缺少定位权限"})
//
// ⚠️ canImport(AMapLocationKit) 守卫:SDK 未链接时 LocationService 抛 sdkNotLinked
// 此处兜底走 stub(与 Phase 2 一致),仅响应 callback 不触发反向 getlocationinfo。
//
import Foundation
import os.log
// 工程默认 SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor,全局 let 也会被 MainActor 隔离;
// handler 闭包是 @Sendable 非隔离上下文,故显式 nonisolatedLogger 本身 Sendable,安全)。
private nonisolated let startLocLog = Logger(subsystem: "ylgamehall", category: "Location")
public enum StartLocationHandler {
/// - Parameter label: 容器标识(`lobby` / `subGame`),仅用于诊断日志。
public static func register(on bridge: any BridgeProtocol, label: String = "?") {
bridge.register("startlocation") { data, callback in
// 与 msext 行为一致:先回 cb 字面,不等定位完成
callback?(.string("startlocation"))
startLocLog.debug("[\(label, privacy: .public)] ← startlocation 入参 type=\(data?.asLooseString ?? "nil", privacy: .public)")
#if canImport(AMapLocationKit)
// SDK 已链接:拉起一次性定位 → 反向 callback 9 字段
// (持续定位 data == 1 暂未实现,业务实际只调一次性 — Phase 5.4 再扩展)
Task { @MainActor in
do {
let payload = try await LocationService.shared.requestOnce(caller: label)
startLocLog.debug("[\(label, privacy: .public)] → getlocationinfo 成功 city=\(payload.city, privacy: .public) province=\(payload.province, privacy: .public)")
bridge.call("getlocationinfo", data: .object([
"address": .string(payload.address),
"city": .string(payload.city),
"cityCode": .string(payload.cityCode),
"country": .string(payload.country),
"district": .string(payload.district),
"latitude": .string(payload.latitude), // ← string
"longitude": .string(payload.longitude), // ← string
"province": .string(payload.province), // ← 小写 p
"street": .string(payload.street)
]), callback: nil)
} catch LocationError.authorizationDenied {
// 契约失败回包(msext gameController.m:2507 等价)
startLocLog.error("[\(label, privacy: .public)] → getlocationinfo 失败:authorizationDenied")
bridge.call("getlocationinfo", data: .object([
"errorCode": .number(12),
"errorMsg": .string("缺少定位权限")
]), callback: nil)
} catch {
// 其它失败也归一到 12(msext 行为)
startLocLog.error("[\(label, privacy: .public)] → getlocationinfo 失败:\(String(describing: error), privacy: .public)")
bridge.call("getlocationinfo", data: .object([
"errorCode": .number(12),
"errorMsg": .string("缺少定位权限")
]), callback: nil)
}
}
#endif
}
}
}