iPhone 12及以上机型DatePicker调用showAndWait时对话框失效问题
问题复现条件
- 受影响设备:iPhone 12及更高版本机型
- 触发操作:调用
showAndWait方法唤起DatePicker控件 - 异常表现:
- 触发时无任何报错、异常栈信息输出
- DatePicker对话框无法正常弹出
- 页面所有交互、返回操作完全失效,用户只能强制关闭应用
问题根因
该异常本质是UI线程死锁:showAndWait属于阻塞式模态调用方法,执行后会立刻阻塞JavaFX应用线程,等待对话框关闭后才会返回执行结果。Gluon Charm 6.0.6版本的DatePicker控件在A14及以上芯片的iOS设备(对应iPhone 12及更新机型)上,会将弹窗渲染、弹出的任务也投递到当前已被阻塞的JavaFX应用线程队列中,两个任务互相等待对方执行完成,直接触发死锁。旧款iPhone设备的UI调度时序存在差异,不会触发这个等待逻辑,因此仅在新机型上稳定复现。
修复方案
- 推荐方案:替换阻塞式调用逻辑,放弃使用
showAndWait,改用非阻塞的show()方法唤起控件,通过属性监听器获取用户选择结果,代码示例:
DatePicker datePicker = new DatePicker(); // 绑定日期选择监听 datePicker.selectedDateProperty().addListener((observable, oldValue, newValue) -> { if (newValue != null) { // 此处编写日期选中后的业务处理逻辑 LocalDate selectedDate = newValue; } }); datePicker.show();
- 临时兼容方案:如果暂时不想重构原有阻塞式业务逻辑,可将
showAndWait调用包裹在Platform.runLater中投递到UI线程队列尾部,规避线程抢占导致的死锁,代码示例:
Platform.runLater(() -> { Optional<LocalDate> pickResult = datePicker.showAndWait(); // 此处处理日期选择返回结果 });
注意:该方案需避免多层Platform.runLater嵌套调用,否则仍可能触发时序问题导致死锁
- 版本升级方案:直接将Gluon Charm依赖升级到6.1.0及以上版本,官方已在新版本中修复了高版本iOS设备上模态控件的线程调度死锁问题。
内容的提问来源于stack exchange,提问作者wstech
相关产品推荐
相关产品推荐

