【问题标题】:SwiftUI: onCommit triggered when is when I click away rather than press ReturnSwiftUI:当我点击离开而不是按回车时触发 onCommit
【发布时间】:2020-05-29 01:09:01
【问题描述】:

我正在使用 onCommit 在 SwiftUI 中创建文本视图(该应用适用于 MacOS)。

struct TextBlockView: View {
     @State private var content = ""
    var id = UUID()

       var body: some View {

        let block = MacEditorTextView(text: $content, onEditingChanged: {
            print("editing changed")
        }, onCommit: {
            Keystroke.keystroke.enterPressed = true
            print("add new textblock here")
            //trigger function to create next block
           }).multilineTextAlignment(.leading)
               .frame(minWidth: 300,
                      maxWidth: .infinity,
                      minHeight: 40,
                      maxHeight: .infinity)
                .focusable()

        let tag = Rectangle()
                    .fill(Color.init(red: 1.00, green: 0.95, blue: 0.80, opacity: 1))
                    .frame(width: 10, height: 10)


        return HStack {
            tag
            block
        }
       }
}

当用户点击离开文本块(添加一个新的文本块)时,会发生所需的操作。但是,我希望在用户点击返回时发生此操作。当我第一次为 onCommit 编写代码时,它以这种方式工作了大约 30 分钟,然后它决定提交是单击而不是按下返回键。

我尝试使用“onCommand”而不是 onCommit,但这不起作用,我不确定是否使用了适当的选择器。我还尝试捕获在 NSWindow 级别按下回车键的时间。但是,我认为这是不希望的,因为我不希望在按下回车键时执行此操作。

非常感谢有关 onCommit 与特定键(返回)的任何帮助。

我是 StackOverflow 的新手,如果需要更多信息,请告诉我。

【问题讨论】:

  • 标准TextField不会发生这种情况,所以我认为它已被使用MacEditorTextView。你会显示它的代码吗?
  • MacEditorTextView 实际上是一个 NSTextView 的包装器,因此它可以用于 SwiftUI。可以在这里找到:gist.github.com/unnamedd/6e8c3fbc806b8deb60fa65d6b9affab0

标签: textview swiftui keystroke


【解决方案1】:

你可以实现这样的东西。当您单击蓝色框时,它会发送一个单曲表示您拥有。将框放在文本框后面。

快速剪切粘贴,比您真正需要的代码多得多,您也可以对这个答案进行一些修剪。

import SwiftUI
import Combine

let saidNDone = PassthroughSubject<Void, Never>()

struct ContentView: View {
var body: some View {
    Example1()
}
}

struct Example1: View {
@State var viewState: CGSize = .zero
@State var dragState: CGSize = .zero
@State var touched = false

var body: some View {
    let dragGesture = DragGesture(minimumDistance: 0, coordinateSpace: CoordinateSpace.global)
        .onChanged { (value) in
            self.dragState = value.translation
    }.onEnded { (value) in
        self.viewState.width += value.translation.width
        self.viewState.height += value.translation.height
        self.dragState = .zero
        saidNDone.send()
    }
    return VStack {
        Rectangle().foregroundColor(.blue).frame(width: 100, height: 100)
        .offset(x: dragState.width + viewState.width,
                y: dragState.height + viewState.height)
        .gesture(dragGesture)
        Text("Hello World ")
          .onReceive(saidNDone) { ( _ ) in
            self.touched = true
          }
        .foregroundColor(self.touched ? Color.red: Color.black)
    }
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
    ContentView()
}
}

【讨论】:

  • 你好,也许我理解错了,但这会在点击时发出信号吗?我想在用户键盘上按下 Enter/Return 键时触发一个动作(或接收一个信号)。
  • 是的,点击会发送多个信号
【解决方案2】:

我不是通过使用 onCommit 而是在 NSTextView 包装器中包含这个函数来解决我的问题:

        func textView(_ textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
             if (commandSelector == #selector(NSResponder.insertNewline(_:))) {
                            // Do something against ENTER key
                            print("enter")
                            //triggers function to create next block.
                            Keystroke.keystroke.enterPressed = true
                            return true
                        } else if (commandSelector == #selector(NSResponder.deleteForward(_:))) {
                            // Do something against DELETE key
                            return true
                        } else if (commandSelector == #selector(NSResponder.deleteBackward(_:))) {
                            // Do something against BACKSPACE key
                            return true
                        } else if (commandSelector == #selector(NSResponder.insertTab(_:))) {
                            // Do something against TAB key
                            return true
                        } else if (commandSelector == #selector(NSResponder.cancelOperation(_:))) {
                            // Do something against ESCAPE key
                            return true
                        }
            return false
        }

注意,这是在符合 NSTextViewDelegate 和 NSControlTextEditingDelegate 协议的协调器中编写的。我不确定是哪一个特别导致它起作用。

如果有人将来遇到这个问题并偶然发现这篇文章,请随时与我联系。

【讨论】:

  • 如果你能扩展这个方法会很高兴 - 不知道如何用 SwiftUI 实现它。我已经厌倦了 MacOS 的 swift 是二等公民,到处都缺少 UI 功能和错误。
  • 嗨!我也非常非常非常厌烦它,并感受到你的痛苦。我把这个函数放到了我的 NSTextViewDelegate 协调器类中。这个类也符合 NSControlTextEditingDelegate 协议,这是它工作所必需的。希望有帮助吗?
  • 您好,我最终使用@Published 发布了TextField 视图,然后使用带有cancellable、sink 和debounce 的组合框架来运行我需要的功能。这很痛苦,因为发布者在值更改之前发出,因此函数在启动时运行 - 在其他变量(如来自 api 的令牌;)设置之前。我将函数设置为有条件的,因此它仅在令牌有效时运行,但这似乎是一个 hack。还是谢谢!
猜你喜欢
  • 1970-01-01
  • 2014-01-05
  • 2013-05-25
  • 1970-01-01
  • 1970-01-01
  • 2013-08-12
  • 2011-11-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多