如何通过代码触发SwiftUI DatePicker弹窗?
如何通过按钮触发SwiftUI DatePicker弹出选择器?
我有一个SwiftUI的DatePicker,正常点击日期文本(比如“Jan 11 2023”)时会弹出选择器。现在想实现:点击界面上其他按钮时,自动弹出这个DatePicker的选择器,请问有没有可行的实现方式?
我使用的DatePicker代码如下:
DatePicker("Jump to", selection: $date, in: dateRange, displayedComponents: [.date])
我测试了@rob mayoff的解决方案,但未成功。在Xcode 14.2、iPhone 14 iOS 16.2模拟器及真机上测试时,triggerDatePickerPopover()确实被调用,但始终执行不到button.accessibilityActivate()这一步。
测试代码如下:
import SwiftUI struct ContentView: View { @State var date: Date = .now let dateRange: ClosedRange<Date> = Date(timeIntervalSinceNow: -864000) ... Date(timeIntervalSinceNow: 864000) var pickerId: String { "picker" } var body: some View { VStack { DatePicker( "Jump to", selection: $date, in: dateRange, displayedComponents: [.date] ) .accessibilityIdentifier(pickerId) Button("Clicky") { triggerDatePickerPopover() print("Clicky Triggered") } } .padding() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } extension NSObject { func accessibilityDescendant(passing test: (Any) -> Bool) -> Any? { if test(self) { return self } for child in accessibilityElements ?? [] { if test(child) { return child } if let child = child as? NSObject, let answer = child.accessibilityDescendant(passing: test) { return answer } } for subview in (self as? UIView)?.subviews ?? [] { if test(subview) { return subview } if let answer = subview.accessibilityDescendant(passing: test) { return answer } } return nil } } extension NSObject { func accessibilityDescendant(identifiedAs id: String) -> Any? { return accessibilityDescendant { // For reasons unknown, I cannot cast a UIView to a UIAccessibilityIdentification at runtime. return ($0 as? UIView)?.accessibilityIdentifier == id || ($0 as? UIAccessibilityIdentification)?.accessibilityIdentifier == id } } func buttonAccessibilityDescendant() -> Any? { return accessibilityDescendant { ($0 as? NSObject)?.accessibilityTraits == .button } } } extension ContentView { func triggerDatePickerPopover() { if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = scene.windows.first, let picker = window.accessibilityDescendant(identifiedAs: pickerId) as? NSObject, let button = picker.buttonAccessibilityDescendant() as? NSObject { print("triggerDatePickerPopover") button.accessibilityActivate() } } }
更新记录
- 更新2:按照调试指引操作后发现,即使代码完全一致,检查器中仍缺少accessibility标识符,暂时不清楚原因。
- 更新3:@rob mayoff的解决方案其实非常有效!如果使用时遇到问题,可以稍等片刻,可能是设备或模拟器正在准备无障碍功能导致的延迟。
内容的提问来源于stack exchange,提问作者Legolas Wang
相关产品推荐
相关产品推荐

