Commit Graph
4 Commits
Author SHA1 Message Date
joywayerandClaude Opus 4.7 d38ff0f8c4 Phase 2.A:大厅 8 个简单 handler 落地 + BridgeData 加 nonisolated
闭合 Phase 1.17 联调最后一公里(解决 Xcode 日志 4 个 "no handler registered"
+ 提前落地 4 个无外部依赖的简单 handler)。

新增 7 个 handler 模块(Source/Bridge/Handlers/):
  - ClipboardHandler.swift           §3.1 [13][14]剪贴板 UIPasteboard.general
  - ShakeHandler.swift               §3.1 [7][8][9]摇一摇 + §3.2 [5]shakeEnd 反向
                                       canShake / canVoice 状态 + motionEnded 转发钩子
  - VoicePlayingHandler.swift        §3.1 [6]actor VoiceCenter.shared 开关位
  - DeviceInfoHandler.swift          §3.1 [21]+ §3.2 [1]getphoneInfo 大写 I 入、
                                       getphoneinfo 小写 i 出反向 callback
                                       DeviceInfoSnapshot 6 字段(IDFA 用 idfv 兜底,
                                       CLAUDE.md 不接 ATT/IDFA)
  - BrowserHandler.swift             §3.1 [16]UIApplication.open async(Task @MainActor
                                       异步打开,闭包先 cb 不等 open 完成)
  - OpenSaomaHandler.swift           §3.1 [22]空 stub(契约要求注册)
  - StartLocationHandler.swift       §3.1 [20]Phase 5 完整实现,Phase 2 stub

扩展 VibratorHandler.swift:
  - §3.1 [10]vibrator(原有)+ [11]repeatvibrator(msext RootVC.m:1820 沿用:
    实际单次 vibrate 不真循环)+ [12]canclevibrator

BridgeProtocol.swift BridgeData 加 nonisolated:
  - 项目默认 SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor 让 BridgeData 跨 actor
    访问被拦;asString / asDouble / asInt / asBool / asArray / asObject /
    subscript 全部标 nonisolated(纯值类型本就该是 isolation-free)
  - 影响所有 @Sendable async handler 闭包内的 data?.asXxx 访问

WebContainerViewController 接入:
  - 加 private let shakeHandler = ShakeHandler() 持有
  - registerBridgeHandlers() 注册 8 个 handler 模块
  - 加 canBecomeFirstResponder = true + viewDidAppear becomeFirstResponder
  - 加 motionEnded(_:with:) 转发到 shakeHandler.handleMotionEnded
    (motion 检测必需 first responder,否则不触发)

BuildProject 通过。重装 app 后 H5 启动应不再报 "no handler registered" 错误。

Plan §5 Phase 2.A 全部勾选(含 startlocation bonus stub + BridgeData
nonisolated 重构)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-22 18:38:00 +08:00
joywayerandClaude Opus 4.7 6c943e2924 Phase 1.15:VibratorHandler 单次振动 handler
新增 ylgamehall/Source/Bridge/Handlers/VibratorHandler.swift:
- 无状态 public enum VibratorHandler,static func register(on:)
- 入参忽略(参考原 msext RootVC.m:1816-1818:time 参数实际不读取)
- 副作用:AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
- responseCallback:.string("vibrator"),与契约 §3.1 [10]一致
- 模拟器无振动硬件、调用静默忽略;真机才能感知

WebContainerViewController.viewDidLoad 新增 registerBridgeHandlers()
单一聚合点,Phase 2+ 在此追加更多 handler,便于发现 / 调试。

repeatvibrator / canclevibrator 严格守住 Plan §5 Phase 2.2 范围,不
提前实现。

BuildProject 通过

Plan 进度已勾选(§5 Phase 1.15 + §8)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-22 04:02:33 +08:00
joywayer 4a6b1e1631 Phase 1.7:BridgeBus 实现 H5↔Native 消息总线 + WKScriptMessageHandler
桥核心的运行时层:把 BridgeProtocol 落到 WKWebView 上,承担 JS → Native
消息分发 + Native → H5 主动调用 + 双向 callback 配对。

- 新增 ylgamehall/Source/Bridge/BridgeBus.swift
  - @MainActor final class,BridgeProtocol + WKScriptMessageHandler 双重
    conform;init(webView:, controller:) 自动向 controller 注册 WVJBHandler
    通道
  - JS → Native(userContentController:didReceive:)
    - body 兼容单条 dict 与 batch [[dict]]
    - 优先识 responseId → 查 pendingCallbacks 派给 Native 端 callback
    - 否则按 handlerName 查 handlers,构造异步 responseCallback 闭包,
      handler 是 @Sendable async 用独立 Task 执行
  - Native → H5(call(_:data:callback:))
    - 拼 payload {handlerName, data, callbackId?},base64 后注入
      WebViewJavascriptBridge._handleMessageFromObjC('<base64>')
    - callback 用 nativeCallbackCounter 递增成 objc_cb_<n> 入
      pendingCallbacks,等 JS 响应回收
  - sendResponseToJS:拼 {responseId, responseData} 走同一通道
  - makeResponseCallback 辅助方法:把多层嵌套闭包拆出来,避免
    Swift 6 类型推断在深嵌套 + actor 隔离上 ICE
- 资源生命周期:webView 弱引用避免循环;BridgeBus 由 controller.add(self)
  retains,WebView 释放后 controller 一并清空 handler 列表自然 release
- BuildProject 通过,Swift 6 严格并发 0 warning;下一步 Phase 1.8 注入
  marcuswestin/WVJB JS 端配套协议即可双向消息打通
2026-06-22 00:11:54 +08:00
joywayer f740274d59 Phase 1.6:BridgeProtocol + BridgeData 协议骨架
桥核心的纯类型层,不依赖 WKWebView,便于 Phase 1.7 BridgeBus 实现与
单测注入 mock 都基于此抽象。

- 新增 ylgamehall/Source/Bridge/BridgeProtocol.swift
  - protocol BridgeProtocol: AnyObject, Sendable
    - register(_:handler:) 注册 H5 → Native handler,重复名覆盖
    - call(_:data:callback:) Native → H5 主动调用,callback 可选
  - typealias BridgeHandler = @Sendable (BridgeData?, BridgeCallback?)
    async -> Void,允许 handler 内部 await
  - typealias BridgeCallback = @Sendable (BridgeData?) -> Void
  - enum BridgeData: Sendable 六态(string/number/bool/null/array/object),
    与 JSON 值同构
- BridgeData JSON 互转:
  - init?(jsonObject:) 从 JSONSerialization 输出递归构造;NSNumber
    Bool/Double 鉴别用 CFGetTypeID 避免 NSNumber(value:true) 被当 1.0
  - var jsonObject: Any 反向,供 evaluateJavaScript 拼 JSON 字符串
- BridgeData 访问语法糖:asString/asInt/asDouble/asBool/asArray/asObject
  + subscript(key:) 对象字段访问 + subscript(index:) 数组访问
- BridgeData 字面量构造:ExpressibleByStringLiteral/IntegerLiteral/
  FloatLiteral/BooleanLiteral/ArrayLiteral/DictionaryLiteral,
  fixture / handler 代码 ["k": 1, "v": true] 直接构造 .object
- BuildProject 通过,Sendable 全自动派生
2026-06-22 00:05:26 +08:00