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>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
0a313afe8e
commit
d38ff0f8c4
@@ -17,6 +17,10 @@ public final class WebContainerViewController: UIViewController {
|
||||
private let bridgedWebView = BridgedWebView()
|
||||
private let splash = SplashOverlay()
|
||||
|
||||
// MARK: - Handlers (有状态的 handler 注册器持有,无状态的走 enum 静态 register)
|
||||
|
||||
private let shakeHandler = ShakeHandler()
|
||||
|
||||
// MARK: - Boot pipeline 内部错误分类
|
||||
//
|
||||
// 用 enum 区分"终态阻塞"与"系统级错误":
|
||||
@@ -47,10 +51,37 @@ public final class WebContainerViewController: UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
/// 注册所有 H5 → Native handler。Phase 1.15 仅 `vibrator`;
|
||||
/// 后续 Phase 2+ 在此追加更多 handler(保持单一聚合点便于发现 / 调试)。
|
||||
/// 注册所有 H5 → Native handler 的单一聚合点。
|
||||
/// Phase 1.15 仅 vibrator;Phase 2.A 扩展到 8 个 handler 模块。
|
||||
private func registerBridgeHandlers() {
|
||||
VibratorHandler.register(on: bridgedWebView.bridge)
|
||||
let bridge = bridgedWebView.bridge
|
||||
|
||||
// Phase 1.15
|
||||
VibratorHandler.register(on: bridge) // §3.1 [10][11][12]扩展
|
||||
|
||||
// Phase 2.A 大厅简单 handler(无外部依赖)
|
||||
ClipboardHandler.register(on: bridge) // §3.1 [13][14]
|
||||
shakeHandler.register(on: bridge) // §3.1 [7][8][9] + §3.2 [5]
|
||||
VoicePlayingHandler.register(on: bridge) // §3.1 [6]
|
||||
DeviceInfoHandler.register(on: bridge) // §3.1 [21] + §3.2 [1]
|
||||
BrowserHandler.register(on: bridge) // §3.1 [16]
|
||||
OpenSaomaHandler.register(on: bridge) // §3.1 [22]空 stub
|
||||
StartLocationHandler.register(on: bridge) // §3.1 [20]Phase 5 完整实现,Phase 2 stub
|
||||
}
|
||||
|
||||
// MARK: - 摇一摇支持
|
||||
// motionEnded 必须 first responder 才触发;canBecomeFirstResponder = true +
|
||||
// viewDidAppear becomeFirstResponder。详见 Design §8.7.1。
|
||||
|
||||
public override var canBecomeFirstResponder: Bool { true }
|
||||
|
||||
public override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
becomeFirstResponder()
|
||||
}
|
||||
|
||||
public override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
|
||||
shakeHandler.handleMotionEnded(motion)
|
||||
}
|
||||
|
||||
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask { .landscape }
|
||||
|
||||
Reference in New Issue
Block a user