在 SwiftUI 中使用 NSTextView 时查找栏不起作用

问题描述 投票:0回答:1

我尝试将查找栏添加到 SwiftUI 视图中的 NSTextView,但尽管设置了必要的属性(usesFindBar、usesFindPanel、isIncrementalSearchingEnabled),但查找栏并未出现。这是我正在使用的代码:

import AppKit

struct TextView: NSViewRepresentable {

    @Binding var selectedRange: NSRange?
    @Binding var text: String
    var onAddingNewLine: (() -> Void)?
    @Binding var textToReplace: (text: String, range: NSRange)?
    @Binding var shouldInsertText: Bool?

    func makeNSView(context: Context) -> NSScrollView {
        let scrollView = NSTextView.scrollableTextView()
        guard let textView = scrollView.documentView as? NSTextView else {
            return scrollView
        }
        textView.allowsUndo = true
        textView.usesFindBar = true
        textView.usesFindPanel = false
        textView.isIncrementalSearchingEnabled = true
        textView.window?.makeFirstResponder(textView)
        textView.isContinuousSpellCheckingEnabled = true
        textView.font = NSFont.monospacedSystemFont(ofSize: 15, weight: .regular)
        textView.textColor = NSColor(Color.onSurface)
        DispatchQueue.main.async {
            textView.string = text
            textView.delegate = context.coordinator
        }
        return scrollView
    }

    func updateNSView(_ scrollView: NSScrollView, context: Context) {
        guard let textView = scrollView.documentView as? NSTextView else {
            return
        }

        if let textToReplace {
            DispatchQueue.main.async {
                let textToInsert = textToReplace
                self.textToReplace = nil
                if shouldInsertText ?? false {
                    textView.insertText(textToInsert.text, replacementRange: textToInsert.range)
                }
                shouldInsertText = false
            }
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, NSTextViewDelegate {

        var parent: TextView

        init(_ parent: TextView) {
            self.parent = parent
        }

        func textDidEndEditing(_ notification: Notification) {
            guard let textView = notification.object as? NSTextView else { return }
            parent.text = textView.string
            textView.undoManager?.removeAllActions()
        }

        func textDidChange(_ notification: Notification) {
            guard let textView = notification.object as? NSTextView else { return }
            let string = textView.string
            let length = string.count
            let insertionPoint = textView.selectedRange.location
            let low = max(0, insertionPoint - 1)

            if let range = Range(NSRange(location: low, length: 1), in: string) {
                let newChar = string[range]

                if length > 0 && length > parent.text.count, newChar == "\n" {
                    parent.text = textView.string
                    parent.onAddingNewLine?()
                } else {
                    parent.text = textView.string
                }
            } else {
                parent.text = textView.string
            }
        }

        func textViewDidChangeSelection(_ notification: Notification) {
            guard let textView = notification.object as? NSTextView else { return }
            parent.selectedRange = textView.selectedRange
        }
    }

}

此属性(usesFindBar、usesFindPanel、isIncrementalSearchingEnabled)在使用通过 Storyboard 创建的 NSTextView 时有效,但在 SwiftUI 中使用时无效。

还使用此 MacEditorTextView

尝试了 Findbar

任何有关查找栏未显示原因的见解将不胜感激!

swift swiftui appkit nstextview nsviewrepresentable
1个回答
0
投票

我能够通过创建此扩展来实现此功能

extension NSTextView {
func showFindBar() {
    let menuItem = NSMenuItem(title: "", action: nil, keyEquivalent: "")
    menuItem.tag = NSTextFinder.Action.showFindInterface.rawValue
    self.performTextFinderAction(menuItem)
} 
}

我也搬到了

textView.window?.makeFirstResponder(textView)
DispatchQueue.main.async

然后我只需通过

.commands { CommandGroup(after: .undoRedo) }

从绑定到键盘快捷键 F 的自定义菜单栏项调用 showFindBar 函数
© www.soinside.com 2019 - 2024. All rights reserved.