【发布时间】:2019-11-05 22:08:59
【问题描述】:
我在 SwiftUI Form 中有一个 Picker,并且我正在尝试在选择器更改时处理该值。我希望能够在代表当前选定值的变量上使用didSet 来执行此操作。
import SwiftUI
struct ContentView: View {
enum TransmissionType: Int {
case automatic
case manual
}
@State private var selectedTransmissionType: Int = TransmissionType.automatic.rawValue {
didSet {
print("selection changed to \(selectedTransmissionType)")
}
}
private let transmissionTypes: [String] = ["Automatic", "Manual"]
var body: some View {
NavigationView {
Form {
Section {
Picker(selection: $selectedTransmissionType,
label: Text("Transmission Type")) {
ForEach(0 ..< transmissionTypes.count) {
Text(self.transmissionTypes[$0])
}
}
}
}
}
}
}
Picker UI (大部分)按预期工作:我可以看到默认值已被选中,点击选择器,它会打开一个新视图,我可以选择其他值,然后返回主表单并显示新值已被选中。但是,永远不会调用 didSet。
我看到了this question,但在我的View 代码中添加更多内容而不是仅在变量更改时处理新值(如果可能的话)似乎很奇怪。使用onReceive 是否更好,即使它会导致更复杂的视图?我的主要问题是:阻止调用 didSet 的代码有什么问题?
我使用this example 来达到这一点。
除了我的常规问题之外,我还有一些关于此示例的其他问题:
A) 我有一个enum 和一个Array 来表示相同的两个值,这似乎很奇怪。有人还可以建议一种更好的方法来构建它以避免这种冗余吗?我考虑过 TransmissionType 对象,但与 enum 相比,这似乎有点过分了……也许不是?
B) 当点击选择器时,带有选择器选项的屏幕会滑过,然后两个选项会向上跳跃一点。这让人感觉刺耳、紧张和糟糕的用户体验。我在这里做错了什么导致糟糕的用户体验吗?或者它可能是一个 SwiftUI 错误?每次更改选择器时都会出现此错误:
[TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window.
【问题讨论】: