ios - FocusedValue / FocusedBinding 在 iPad 上不起作用
问题描述
目标
- 在多平台应用程序(iOS 和 macOS)上使用键盘快捷键
- 点击键盘快捷键时,需要打印价格
问题
- 相同的代码在 iPad 上无效,但在 macOS 上有效
问题:
- 为什么不工作?
- 如何解决这个问题?
环境
- macOS 大苏尔 - 11.6 (20G165)
- 版本 13.0 (13A233)
代码
@main
struct TestApp: App {
@State private var price = 0
var body: some Scene {
WindowGroup {
ContentView(price: $price)
.focusedValue(\.price, $price)
}
.commands {
PriceCommands()
}
}
}
struct ContentView: View {
@Binding var price: Int
var body: some View {
IncreasePriceButton(price: $price)
}
}
struct IncreasePriceButton: View {
@Binding var price: Int
var body: some View {
Button("Increase Price") {
price += 1
print("price = \(price)")
}
}
}
struct PriceCommandButton: View {
@FocusedBinding(\.price) var price
var body: some View {
Button("Print Price") {
print("price = \(price)")
}
}
}
struct PriceCommands: Commands {
var body: some Commands {
CommandMenu("Custom") {
PriceCommandButton()
.keyboardShortcut(KeyboardShortcut("C", modifiers: [.command, .shift]))
}
}
}
struct FocusedPriceKey: FocusedValueKey {
typealias Value = Binding<Int>
}
extension FocusedValues {
var price: FocusedPriceKey.Value? {
get { self[FocusedPriceKey.self] }
set { self[FocusedPriceKey.self] = newValue }
}
}
解决方案
所以我拿了演示代码并添加了一点调试,如下所示。
据我所知,有两个问题。
首先,没有设置focusedValue
on ContentView
,因为 View 没有被聚焦。可以看出这是因为@FocusBinding
inOtherView
没有price
按预期获取值。
这可能是一个 SwiftUI 错误,但通过切换到focusedSceneValue
修改器很容易解决。无论如何,有了它,就可以price
保持同步。ContentView
OtherView
第二个问题是,即使第一个修复/解决方法到位,更改price
也不会导致Custom
菜单在初始渲染后重建。
我认为这是 SwiftUI 的一个错误,建议向 Apple 提交反馈,让他们知道。
作为应用程序全局状态的解决方法(在这种情况下)price
将只是将其PriceCommands
作为参数传递(正如已经为 所做的那样ContentView
)。
亲切的问候
import SwiftUI
@main
struct TestApp: App {
@State private var price = 0
var body: some Scene {
WindowGroup {
ContentView(price: $price)
.focusedSceneValue(\.price, $price) // <== Changed
}
.commands {
PriceCommands()
}
}
}
struct OtherView: View {
@FocusedBinding(\.price) var price: Int?
var body: some View {
Text("OtherView price = \(String(describing: price))")
}
}
struct ContentView: View {
@Binding var price: Int
var body: some View {
VStack {
OtherView()
IncreasePriceButton(price: $price)
}
}
}
struct IncreasePriceButton: View {
@Binding var price: Int
var body: some View {
Button("Increase Price") {
price += 1
print("price = \(price)")
}
}
}
struct PriceCommandButton: View {
@FocusedBinding(\.price) var price
var priceText: String {
String(price ?? -1)
}
var body: some View {
print("Buiding commands menu with \(String(describing: price))")
return Button("Print Price \(priceText)") {
print("price = \(String(describing: price))")
}
}
}
struct PriceCommands: Commands {
var body: some Commands {
CommandMenu("Custom") {
PriceCommandButton()
.keyboardShortcut(KeyboardShortcut("C", modifiers: [.command, .shift]))
}
}
}
struct FocusedPriceKey: FocusedValueKey {
typealias Value = Binding<Int>
}
extension FocusedValues {
var price: FocusedPriceKey.Value? {
get { self[FocusedPriceKey.self] }
set { self[FocusedPriceKey.self] = newValue }
}
}
推荐阅读
- ruby - CirclesController 中的 NoMethodError#add undefined method `circle' for nil:NilClass
- r - 如何从 data.tables 列表中计算每组的平均值?
- linux - 在 1200 Linux 服务器中安装脚本文件
- java - Spring 事务中 REQUIRES_NEW 和 NESTED 传播的行为差异
- node.js - Apache 将节点应用程序重定向到具有 .htaccess 的文件夹
- excel - 在 Excel 中编写 if 条件
- javascript - Multiple random id in element
- c# - Web.API 2 控制器操作中的异步/等待
- c# - 从动态创建的文本框抓取输入到另一个表单
- c++ - 如何引用二维指针?