0

我正在使用此处概述的 TextView UIViewRepresentable https://www.appcoda.com/swiftui-textview-uiviewrepresentable/

它按预期工作,除了一个关于行距的问题。SwiftUI 的 lineSpacing 修饰符似乎对它没有任何影响。因此,我通过在 UIViewRepresentable 中添加以下内容来解决它 func updateUIView(_ uiView: UITextView, context: Context)

let style = NSMutableParagraphStyle()
style.lineSpacing = 4
let attributes = [NSAttributedString.Key.paragraphStyle : style]
uiView.attributedText = NSAttributedString(string: self.text, attributes:attributes)

正如调整 UITextView 的行距所建议的那样。

因此,完整的功能如下所示:

func updateUIView(_ uiView: UITextView, context: Context) {
    uiView.text = text
    
    // line spacing
    let style = NSMutableParagraphStyle()
    style.lineSpacing = 4
    let attributes = [NSAttributedString.Key.paragraphStyle : style]
    uiView.attributedText = NSAttributedString(string: self.text, attributes:attributes)
}

这可以完成工作,但是会导致 UndoManager 重置。也就是说,只要我做出任何更改,UndoManager 就不会相信有任何事情可以撤消(或重做)。从我的搜索来看,这似乎是更改属性文本值的一般副作用。我想知道是否有可用的解决方法,无论是对我的方法进行调整还是在重置 UndoManager 状态的情况下实现 lineSpacing 的完全不同的方式。

更新:尝试了 Asperi 的建议,但结果喜忧参半。

这是 TextView 和对应的 Coordinator 的完整代码:

import SwiftUI
 
struct TextView: UIViewRepresentable {
  
// MARK: Bindings
@Binding var text: String
@Binding var textStyle: UIFont.TextStyle

// MARK: -
// MARK: Functions
func makeUIView(context: Context) -> UITextView {
    let textView = UITextView()

    textView.backgroundColor = UIColor.clear
    textView.delegate = context.coordinator
    textView.autocapitalizationType = .sentences
    textView.isSelectable = true
    textView.isUserInteractionEnabled = true
    textView.adjustsFontForContentSizeCategory = true
    
    return textView
}

func makeCoordinator() -> Coordinator {
    Coordinator($text)
}

func updateUIView(_ uiView: UITextView, context: Context) {

    let storage = uiView.textStorage
     storage.beginEditing()

     // line spacing
     let style = NSMutableParagraphStyle()
     style.lineSpacing = 4
     let attributes = [NSAttributedString.Key.paragraphStyle : style]
     storage.replaceCharacters(in: NSRange(location: 0, length: storage.length),
         with: NSAttributedString(string: self.text, attributes:attributes))
     storage.endEditing()
}

// MARK: -

// MARK: Internal classes

class Coordinator: NSObject, UITextViewDelegate {
    
    // MARK: Local
    var text: Binding<String>
    
    // MARK: -

    init(_ text: Binding<String>) {
        self.text = text
    }
 
    // MARK: -

    // MARK: Functions
    func textViewDidChange(_ textView: UITextView) {
        self.text.wrappedValue = textView.text
    }
}
}

如果我在 textViewDidChange 中保留 self.text.wrappedValue = textView.text (取自顶部链接的 AppCoda 教程),那么该建议不起作用。但是,如果我删除它,它似乎可以工作,但还有其他问题,即每当刷新视图(我认为)时,文本会在会话开始时自动重置为原始状态 - 例如,如果我尝试切换到另一个应用程序,我可以在这样做之前看到文本重置,或者当我打开一段 UI 时,例如,降低了 TextView 的不透明度。

4

1 回答 1

0

由于 Ivan 在https://stackoverflow.com/a/44414510/698971中的回答,我可能偶然发现了正确的方法。

func makeUIView(context: Context) -> UITextViewTextView UIViewRepresentable 里面我需要添加:

    let spacing = NSMutableParagraphStyle()
    spacing.lineSpacing = 4
    let attr = [NSAttributedString.Key.paragraphStyle : spacing]
    textView.typingAttributes = attr
于 2020-12-09T16:34:05.227 回答