16.6 C
London
Friday, September 20, 2024

ios – Embedding a distant picture in a textual content utilizing TextKit2


I’m making an attempt to embed a distant picture obtained from a URL right into a textual content utilizing TextKit2

I am utilizing NSTextAttachmentViewProvider however I can not get it to work as anticipated.

There are two issues I can not perceive.

The conduct appears to be like like this

enter picture description right here

The code appears to be like like this

import SwiftUI
import SDWebImageSwiftUI

struct ContentView: View {

    @State personal var textual content = "check"

    var physique: some View {
        MFMTextView(textual content: $textual content)
            .body(maxWidth: .infinity)
    }
}

let oyasu = URL(string:  "https://media.misskeyusercontent.jp/misskey/f75cd6a7-61f9-4e72-b47f-9ce0b5aa8602.png")!

struct MFMTextView: UIViewRepresentable {

    @Binding var textual content: String

    typealias UIViewType = UITextView

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

    func updateUIView(_ uiView: UITextView, context: Context) {
        let attributedText = NSMutableAttributedString()

        attributedText.append(NSAttributedString(string: textual content))
        attributedText.append(NSAttributedString(attachment: ImageAttachment(url: oyasu)))
        attributedText.append(NSAttributedString(string: textual content))
        uiView.attributedText = attributedText
    }

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

    class Coordinator: NSObject, UITextViewDelegate {
        var mum or dad: MFMTextView

        init(_ mum or dad: MFMTextView) {
            self.mum or dad = mum or dad
        }

        func textViewDidChange(_ textView: UITextView) {

        }
    }
}

remaining class ImageAttachment: NSTextAttachment {
    let imageUrl: URL

    init(url: URL) {
        self.imageUrl = url
        tremendous.init(information: nil, ofType: nil)
        allowsTextAttachmentView = true
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been carried out")
    }

    override func viewProvider(
        for parentView: UIView?,
        location: NSTextLocation,
        textContainer: NSTextContainer?
    ) -> NSTextAttachmentViewProvider? {
        let viewProvider = ImageAttachmentViewProvider(
            textAttachment: self,
            parentView: parentView,
            textLayoutManager: textContainer?.textLayoutManager,
            location: location,
            imageUrl: imageUrl
        )
        return viewProvider
    }
}

remaining class ImageAttachmentViewProvider: NSTextAttachmentViewProvider {
    let imageUrl: URL

    init(
        textAttachment: NSTextAttachment,
        parentView: UIView?,
        textLayoutManager: NSTextLayoutManager?,
        location: NSTextLocation,
        imageUrl: URL
    ) {
        self.imageUrl = imageUrl
        tremendous.init(
            textAttachment: textAttachment,
            parentView: parentView,
            textLayoutManager: textLayoutManager,
            location: location
        )
        tracksTextAttachmentViewBounds = true
    }

    override func loadView() {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        SDWebImageDownloader.shared.downloadImage(with: imageUrl) { [weak self] (picture, _, _, _) in
            DispatchQueue.foremost.async { [weak self] in
                imageView.picture = picture

                self?.updateViewSize(for: picture)
            }
        }

        self.view = imageView
        self.view?.body.measurement.top = 25.0
    }

    personal func updateViewSize(for picture: UIImage?) {
        guard let picture = picture else { return }
        let aspectRatio = picture.measurement.width / picture.measurement.top
        let top: CGFloat = 25
        let width = top * aspectRatio

        // Replace the view body with the brand new measurement
        view?.body = CGRect(
            x: 0.0,
            y: 0.0,
            width: width,
            top: top
        )

        print(picture.measurement.width)
        print(picture.measurement.top)

        // Drive structure replace
        view?.setNeedsLayout()
        view?.layoutIfNeeded()
    }

    override func attachmentBounds(
        for attributes: [NSAttributedString.Key : Any],
        location: NSTextLocation,
        textContainer: NSTextContainer?,
        proposedLineFragment: CGRect,
        place: CGPoint
    ) -> CGRect {
        guard let imageView = view as? UIImageView, let picture = imageView.picture else {
            return .zero
        }
        let top = 25.0

        let aspectRatio = picture.measurement.width / picture.measurement.top
        let width = top * aspectRatio

        return CGRect(
            x: 0.0,
            y: 0.0,
            width: width,
            top: 100.0
        )
    }
}

Do you will have any good concepts?

Or know of some good pattern code?

Latest news
Related news

LEAVE A REPLY

Please enter your comment!
Please enter your name here