我正在为我的 SwiftUI 应用程序使用视图模型,并且希望在视图模型中也具有焦点状态,因为表单非常复杂。
在视图中使用 @FocusState 的实现按预期工作,但不是我想要的:
import Combine
import SwiftUI
struct ContentView: View {
@ObservedObject private var viewModel = ViewModel()
@FocusState private var hasFocus: Bool
var body: some View {
Form {
TextField("Text", text: $viewModel.textField)
.focused($hasFocus)
Button("Set Focus") {
hasFocus = true
}
}
}
}
class ViewModel: ObservableObject {
@Published var textField: String = ""
}
Run Code Online (Sandbox Code Playgroud)
如何将 @FocusState 放入视图模型中?
ViewModel假设你也有
class ViewModel: ObservableObject {
@Published var hasFocus: Bool = false
...
}
Run Code Online (Sandbox Code Playgroud)
你可以像这样使用它
struct ContentView: View {
@ObservedObject private var viewModel = ViewModel()
@FocusState private var hasFocus: Bool
var body: some View {
Form {
TextField("Text", text: $viewModel.textField)
.focused($hasFocus)
}
.onChange(of: hasFocus) {
viewModel.hasFocus = $0 // << write !!
}
.onAppear {
self.hasFocus = viewModel.hasFocus // << read !!
}
}
}
Run Code Online (Sandbox Code Playgroud)
以及Button如果需要的话同样的。
我遇到了同样的问题,最终编写了一个可以重用来同步两个值的扩展。这样,如果需要,也可以从视图模型侧设置焦点。
class ViewModel: ObservableObject {
@Published var hasFocus: Bool = false
}
struct ContentView: View {
@ObservedObject private var viewModel = ViewModel()
@FocusState private var hasFocus: Bool
var body: some View {
Form {
TextField("Text", text: $viewModel.textField)
.focused($hasFocus)
}
.sync($viewModel.hasFocus, with: _hasFocus)
}
}
extension View {
func sync<T: Equatable>(_ binding: Binding<T>, with focusState: FocusState<T>) -> some View {
self
.onChange(of: binding.wrappedValue) {
focusState.wrappedValue = $0
}
.onChange(of: focusState.wrappedValue) {
binding.wrappedValue = $0
}
}
}
Run Code Online (Sandbox Code Playgroud)
@Published var hasFocus: Bool在 ViewModel 中创建一个并同步它:
Form
...
.onAppear { self.hasFocus = viewModel.hasFocus}
.onChange(of: hasFocus) { viewModel.hasFocus = $0 }
.onChange(of: viewModel.hasFocus) { hasFocus = $0 }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4495 次 |
| 最近记录: |