如何在 SwiftUI macOS 中创建第一响应者

Posted

技术标签:

【中文标题】如何在 SwiftUI macOS 中创建第一响应者【英文标题】:How to make first responder in SwiftUI macOS 【发布时间】:2020-04-18 22:09:14 【问题描述】:

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

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*/ 

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

【问题讨论】:

MyField 是继承自 NSTextField 还是聚合它?你能提供代码吗? 【参考方案1】:

如果您的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
  

【讨论】:

这种方法是一种可行的方法。所以我会选择你的作为有效答案。我找到了一种不同的方法,我将在下面发布。谢谢你的回答【参考方案2】:

@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
      

【讨论】:

以上是关于如何在 SwiftUI macOS 中创建第一响应者的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot 应用程序中创建第二个 RedisTemplate 实例

如何在我的项目中创建第二个目标来为 iOS 创建一个预填充的数据库

如何在 swiftUI 中创建具有多列的列表?

在 R Shiny 中创建第二个 UI 元素

c ++在第一类的构造函数中创建第二类的对象 - 多线程

在 ADT Mac Bundle 中创建第一个 android 应用程序时出现 java.lang.NullPointerException