SwiftUI中的多行可编辑文本字段

3

我想在Swift UI for macOS中创建可编辑的多行文本框。我想创建一个语法高亮文本编辑器,所以它应该是多行的,并且可以在不同的行上更改样式。在当前状态下,这个框架是否支持?在网上几乎找不到相关文档。


看起来 SwiftUI 现在有一个 TextEditor 组件,链接为:https://developer.apple.com/documentation/swiftui/texteditor 但是它不支持像颜色这样的改变样式途中整个行。 - deeBo
2个回答

1

这可能很有用,这是我使用SwiftUI获取NSTextView的第一种解决方案:

import SwiftUI
import os

let uiLog = OSLog(subsystem: "com.visual-science.CryptiK", category: "UI")

class  EditorCoordinator : NSObject, NSTextViewDelegate {
  let textView: NSTextView;
  let scrollView : NSScrollView
  let text : Binding<NSAttributedString>

  init(binding: Binding<NSAttributedString>) {
    text = binding

    textView = NSTextView(frame: .zero)
    textView.autoresizingMask = [.height, .width]
    textView.textStorage?.setAttributedString(text.wrappedValue)
    textView.textColor = NSColor.textColor

    scrollView = NSScrollView(frame: .zero)
    scrollView.hasVerticalScroller = true
    scrollView.autohidesScrollers = false
    scrollView.autoresizingMask = [.height, .width]
    scrollView.documentView = textView

    super.init()
    textView.delegate = self
  }

  func textDidChange(_ notification: Notification) {
    switch  notification.name {
    case NSText.didChangeNotification :
      text.wrappedValue = (notification.object as? NSTextView)?.textStorage ?? NSAttributedString(string: "")
    default:
      os_log(.error, log: uiLog, "Coordinator received unwanted notification")
    }
  }

}

struct DataTextEditorView: View, NSViewRepresentable {
  typealias Coordinator = EditorCoordinator
  typealias NSViewType = NSScrollView

  let text : Binding<NSAttributedString>

  func makeNSView(context: NSViewRepresentableContext<DataTextEditorView>) -> DataTextEditorView.NSViewType {
    os_log(.info, log: uiLog, "%@", context.coordinator.scrollView)
    return context.coordinator.scrollView
  }

  func updateNSView(_ nsView: NSScrollView, context: NSViewRepresentableContext<DataTextEditorView>) {
    os_log(.debug, log: uiLog, "%@", context.coordinator.self)
    os_log(.debug, log: uiLog, "%@", text.wrappedValue)
  }

  func makeCoordinator() -> EditorCoordinator {
    os_log(.info, log: uiLog, "makeCoordinator")
    let coordinator =  EditorCoordinator(binding: text)
    return coordinator
  }

}

如果像我一样,您只需要编辑一些没有属性的文本,则可以将NSAttributedString替换为String,并针对这种更简单的情况调整代码。

这里有一些重要的内容,SwiftUI结构体被创建了很多次,但是协调器在某种程度上被缓存...然后所有的事情都由协调器真正处理,以避免每次文本更改时都创建一个scrollview+textview :) - igerard

-4
你可以在SwiftUI中使用多行TextField(只需在其上调用.lineLimit(N)即可实现多行),但目前不支持具有多个不同样式的文本。 TextField 只有单一字体和样式。
但是,你可以自己来实现:创建一个 NSViewRepresentable 实现,该实现提供一个 NSTextView 并将其绑定到一个 NSMutableAttributedText 属性。您需要自己处理所有文本视图模型同步和绑定更新,但肯定是可行的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接