How to implement Notes-style attachments in TextEditor with movable/deletable images?

I'm trying to create a Notes-like experience in my SwiftUI app where users can:

  1. Add photos as inline attachments within a TextEditor
  2. Move these attachments around within the text (like they were text characters)
  3. Delete attachments
  4. Preview attachments in full screen
  5. Have the attachments persist with the text content

Similar to how Apple Notes handles attachments, where images become part of the text flow and can be manipulated like text characters.

Current approach: I've tried using a custom TextEditor with a separate array of attachments, but I'm struggling to make the attachments behave as inline elements that can be moved within the text.

RichTextEditor:

struct RichTextEditor: View {
    @State var content: String = ""

    @State private var isGalleryPresented = false
    @State var pickedImage: PhotosPickerItem?
    @State private var selectedImage: UIImage?

    var body: some View {
        TextEditor(text: $content)
            .toolbar {
                ToolbarItemGroup(placement: .keyboard) {
                    Button {
                        isGalleryPresented = true
                    } label: {
                        Label("Attached", systemImage: "paperclip")
                    }
                }
            }
            .photosPicker(isPresented: $isGalleryPresented, selection: $pickedImage)
            .onChange(of: pickedImage) { oldItem, newItem in
                Task {
                    if let pickedImage = pickedImage,
                       let data = try? await pickedImage.loadTransferable(type: Data.self),
                       let loadedImage = UIImage(data: data) {
                        if let imageData = loadedImage.jpegData(compressionQuality: 0.7) {
                            Task {
                                await addPhoto(imageData)
                            }
                       }
                    }
                }
            }
    }

    private func addPhoto(_ imageData: Data) async {
        await MainActor.run {
            let photo = PhotoData(imageData: imageData)
            content += "\n[image:\(photo.id)]"
        }
    }
}

I will need to use UITextView which works with NSAttributedString. To add an image inline, you will need to create an Attachment for NSAttribuedString. Here is a short example:

// create an NSMutableAttributedString that we'll append everything to
let fullString = NSMutableAttributedString(string: "Start of text")

// create our NSTextAttachment
let image1Attachment = NSTextAttachment()
image1Attachment.image = UIImage(named: "awesomeIcon.png")

// wrap the attachment in its own attributed string so we can append it
let image1String = NSAttributedString(attachment: image1Attachment)

// add the NSTextAttachment wrapper to our full string, then add some more text.
fullString.append(image1String)
fullString.append(NSAttributedString(string: "End of text"))

As of today, SwiftUI TextEditor doesn't support rich text editing. If you target to make a rich text editor, UITextView / NSTextView + UIViewRepresentable / NSViewRrepresentable + NSAttribuedString, which allows you to embed an image as a text attachment, as @gahntpo said, will be your better choice for now.

Meanwhile, I’d suggest that you file a feedback report to vote for rich text editing support in SwiftUI, which may help the relevant team prioritize the work.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

How to implement Notes-style attachments in TextEditor with movable/deletable images?
 
 
Q