如何将 @FocusState 与视图模型一起使用?

G. *_*arc 12 swiftui

我正在为我的 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 放入视图模型中?

Asp*_*eri 9

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如果需要的话同样的。


yan*_*xou 7

我遇到了同样的问题,最终编写了一个可以重用来同步两个值的扩展。这样,如果需要,也可以从视图模型侧设置焦点。

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)


Jan*_*ano 6

@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)