swift - 如何在 SwiftUI 中将 NSAttributedString 与 ScrollView 一起使用?

标签 swift uikit swiftui nsattributedstring

我已经能够渲染 NSAttributedString s 通过 UIViewRepresentable在我将 View 包裹在 ScrollView 中之前,它非常有效.

当放置在 ScrollView 内时, NSAttributedString View 停止渲染。

我尝试了一些其他方法来代替 NSAttributedString添加多个 Text() View 一起获取格式,该格式在 ScrollView 中起作用并支持斜体和monospace font .不幸的是,这不适用于 links在文本块内,这意味着我仍然需要一个 NSAttributedString .

import SwiftUI

struct TextWithAttributedString: UIViewRepresentable {

    var attributedString: NSAttributedString

    init(_ attributedString: NSAttributedString) {
        self.attributedString = attributedString
    }

    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView(frame: .zero)
        textView.attributedText = self.attributedString
        textView.isEditable = false
        return textView
    }

    func updateUIView(_ textView: UITextView, context: Context) {
        textView.attributedText = self.attributedString
    }
}


let exampleText = """
Fugiat id blanditiis et est culpa voluptas. Vivamus aliquet enim eu blandit blandit. Sit eget praesentium maxime sit molestiae et alias aut.
"""

struct NSAttributedStringView: View {
    var body: some View {
// Note: when uncommented, the view breaks
//    ScrollView {
        TextWithAttributedString(NSAttributedString(string: exampleText))
//    }
    }
}

struct NSAttributedStringView_Previews: PreviewProvider {
    static var previews: some View {
        NSAttributedStringView()
            .previewLayout(.sizeThatFits)
    }
}

编辑:我尝试使用包裹的 UITextViewtext属性集而不是 attributeText属性,但这也无法在 ScrollView 中呈现,所以问题似乎是 UITextView ,而不是 NSAttributedString .

所以问题是,我们如何获得 UITextViewScrollView 工作?

最佳答案

原因是 SwiftUI ScrollView需要定义的内容大小,但使用了 UITextView本身就是一个 UIScrollView并根据父 View 中的可用空间检测内容。因此它发生了未定义大小的循环。

这是如何解决这个问题的可能方法的简化演示。这个想法是计算 UITextView 的内容大小并将其传递给 SwiftUI ...

struct TextWithAttributedString: UIViewRepresentable {
    @Binding var height: CGFloat
    var attributedString: NSAttributedString

    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView(frame: .zero)
        textView.isEditable = false
        return textView
    }

    func updateUIView(_ textView: UITextView, context: Context) {
        textView.attributedText = self.attributedString

        // calculate height based on main screen, but this might be 
        // improved for more generic cases
        DispatchQueue.main.async { // << fixed 
            height = textView.sizeThatFits(UIScreen.main.bounds.size).height
        }
    }
}


struct NSAttributedStringView: View {
    @State private var textHeight: CGFloat = .zero
    var body: some View {
        ScrollView {
            TextWithAttributedString(height: $textHeight, attributedString: NSAttributedString(string: exampleText))
                .frame(height: textHeight) // << specify height explicitly !
        }
    }
}

关于swift - 如何在 SwiftUI 中将 NSAttributedString 与 ScrollView 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59889020/

相关文章:

ios - 如何在 ObjectMapper 中映射 JSON 字典?

iphone - 以时间间隔链接 UIView 动画

ios - 无法更改 UINavigationBar 提示颜色

SwiftUI 标题字体

ios - 为单个 ViewController/UIcollectionView 使用多个库

swift - 如何将指数值转换为十进制值

ios - 声明 NSDictionary 并将其放入 Swift 中的键值对?

ios - 使用 Quartz2D 删除笔划路径不仅仅是删除路径

ios - Xcode Beta 6 中的 SwiftUI 模式?

ios - 如何在 SwiftUI 中添加背景图像以完成 View