如何在 SwiftUI macOS 中成为第一响应者

How to make first responder in SwiftUI macOS

我正在尝试让我的 textField(NSViewRepresentable 包装 NSTextField)在出现时成为第一响应者。我在这个 中测试了很多答案,但它们要么不起作用:

func updateNSView(_ nsView: MyField, context: Context) {
  if some_condition {
    print(nsViews.becomeFirstResponder()) // returns false
    negate_condition()
  }
  ...
}

或者它与日志一起崩溃 (=== AttributeGraph: cycle detected through attribute 43 ===):

func updateNSView(_ nsViews: MyField, context: Context) {
  if some_condition {
    Window.thisWindow?.makeFirstResponder(nsViews)
    negate_condition()
  }
  ...
}

我想要实现的是:

@State var fieldActive: Bool
body: some View {
  MyField(...).onAppear { /*makeFirstResponder if fieldActive == true*/ }
}

有人可以帮我解决这个问题吗?非常感谢!

如果您的 MyFieldNSTextField 以下作品。使用 Xcode 11.4 / macOS 10.15.4

测试
  func makeNSView(context: Context) -> MyField {
    let view = MyField()

    // ... other properties set up here

    // wait for next cycle, so field be already in window
    DispatchQueue.main.async { 
        view.window?.makeFirstResponder(view)
    }
    return view
  }

@Asperi 提供了一个有效的方法,我找到了另一条通往答案的道路。我使用 SwiftUI-Introspect library 完成了 SwiftUI TextField 的工作(没有包装 NSTextField),这里是代码:

struct SearchBar {
  @Binding var shouldActivate: Bool
  var body: some View {
    TextField("", text: text)
      .textFieldStyle(PlainTextFieldStyle())
      .introspectTextField { textField in 
          if self.shouldActivate {
              textField.becomeFirstResponder()
              self.shouldActivate = false
          }
          textField.focusRingType = .none
      }
}