SwiftUI - Using UIViewRepresentable to wrap view in order to use NSMutableAttributedString

789 Views Asked by At

So in order to use NSMutableAttributedString with SwiftUI i wrapped a view with UIViewRepresentable, the problem is that the layout breaks after as so: enter image description here

this is the result with the usual Text(): enter image description here

This is my vm:

final class ViewModel: ObservableObject, CryptoViewControllerFactoryType {
var firstText: String
var font: Font
var color: Color
var image = "Test"
var attribute: NSMutableAttributedString
var attribute1: NSMutableAttributedString
var attribute2: NSMutableAttributedString
var attribute3: NSMutableAttributedString

@Published var count = 0


init() {
    firstText = "gjhgjhgjhg"
    color = .red
    font = Font.custom("Orion-ExtraBold", size: 35)
    attribute = NSMutableAttributedString(string: " ifjglfjgsnfdiggslifjglfjgsnfdiggslifjglfjgsnfdiggslifjglfjgsnfdiggslifjglfjgsnfdiggslifjglfjgsnfdiggsl", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14),NSAttributedString.Key.foregroundColor: UIColor.red])
    attribute1 = NSMutableAttributedString(string: "ifjglfjgsnfdiggsl;dfgbslfkbg;skjgbsg", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 50),NSAttributedString.Key.foregroundColor: UIColor.red])

and this is the view:

struct TestView: View {
@ObservedObject var viewModel: ViewModel

var body: some View {
    ZStack {
        ScrollView {
            VStack {
                Image(viewModel.image).resizable()
                    .scaledToFit()
                    .overlay(
                        Button(action: {
                            print(">> Trash Tapped")
                            //viewModel.dismiss
                        }) {
                            Image("closeBtn")
                        }.padding(.top, 30)
                            .padding(.trailing, 16),
                        alignment: .topTrailing
                        
                    )
                    .padding(.bottom, 40)
              //  Text("sdfsdfsdfsdfsdsffdsfsfsgsg")
                TextView(text: $viewModel.attribute)
                    .padding(.trailing, 30)
                    .padding(.leading, 30)
                    .padding(.bottom, 40)
                    .multilineTextAlignment(.trailing)

                TextView(text: $viewModel.attribute1)
                    .disabled(true)
                    .fixedSize()
                    .padding(.trailing, 30)
                    .padding(.leading, 30)
                    .padding(.bottom, 40)
                    .multilineTextAlignment(.trailing)
            }
            .frame(alignment: .top)
        }
        .edgesIgnoringSafeArea(.all)
    }
    .navigationBarHidden(true)
}

}

struct TestView_Previews: PreviewProvider {
static var previews: some View {
    TestView(viewModel: ViewModel())
}

}

struct TextView: UIViewRepresentable {
@Binding var text: NSMutableAttributedString

func makeUIView(context: Context) -> UILabel {
    let label = UILabel()
    label.textAlignment = .right
    label.numberOfLines = 0
    //label.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

    return label
}

func updateUIView(_ uiView: UILabel, context: Context) {
    uiView.attributedText = text
}

}

Is there a way to use it correctly ? Thanks in advance!

1

There are 1 best solutions below

0
narek.sv On

Starting from iOS 15 you can use the NSAttributedString directly in Text component using this initializer:

public init(_ attributedContent: AttributedString) // Text

and use this initializer to convert NSAttributedString to AttributedString

public init(_ nsStr: NSAttributedString) // AttributedString