NSTextAttachment view flicker while typing in same paragraph

I using SwiftUI to wrap a NSTextView to support rich text editing. I created a subclass ImageAttachment and provided my own viewProvider and attachmentView. The insertion of the image works fine, but when I typing in the same paragraph of the image, the image will flicker during typing and pause. after typing it sometimes just display nothing, but after refresh or click other places, the image shows.

The interesting part is if I typing in other paragraph, the image attachment displays well.

I don't think the flicker should happen while typing in the same paragraph of the attachment, but not sure if there is a way to enforce the layout stable for the paragraph?

Answered by DTS Engineer in 888120022

Thanks for posting. I built a minimal test to try to reproduce this — a SwiftUI NSViewRepresentable-wrapped NSTextView with a custom NSTextAttachment subclass and a viewProvider returning a custom NSView. I then stress-tested it against five plausible causes, and none of them reproduced any flicker:

  1. Baseline pattern — custom attachment + view provider returning a tinted layer-backed view, type in the same paragraph as the inserted attachment: stable.
  2. No caching in loadView() — every call constructs a brand-new NSView with fresh subviews and constraints: stable.
  3. Aggressive layout invalidation on every keystrokeNSTextLayoutManager.invalidateLayout(for: documentRange) from a textDidChange: delegate: stable.
  4. Mixed content sources — both attachment.image set to a programmatically drawn NSImage and a custom viewProvider returning a separate NSView: stable.
  5. Raster image contentloadView() returns an NSView containing an NSImageView with a real NSBitmapImageRep-backed NSImage instead of a layer-tinted plain view: stable.

That tells me the flicker isn't in any of the most common anti-patterns — it's something specific to your implementation that I haven't anticipated. To narrow it down, could you share the following?

  1. Your ImageAttachment class, including:

    • The viewProvider(for:location:textContainer:) override
    • The NSTextAttachmentViewProvider.loadView() implementation
    • Whatever you mean by "attachmentView" — is that a property you added to your subclass, or are you setting attachment.image, or something else? The exact wiring matters here.
  2. Your NSViewRepresentable (or NSTextView-wrapping code), especially:

    • Any NSTextViewDelegate methods you implement
    • Any textStorageDidProcessEditing: / textDidChange: handlers
    • Any code that re-applies attributes after a text change (for example, syntax highlighting, autocomplete, or formatting updates)
    • Whether you ever call addSubview on the attachment view yourself, rather than letting the framework manage its placement.
  3. Whether you have a custom NSTextStorage subclass. If your storage's processEditing reapplies attributes (including the attachment) on every edit, that could trigger the framework to requery the view.

  4. How your image loads. Is it always available synchronously by the time loadView() runs, or is there an async fetch (network, disk, render queue) that makes the image briefly unavailable on each load? An async load on every paragraph relayout would look exactly like flicker.

  5. macOS version you're targeting and testing on. The TextKit 2 vs TextKit 1 default and several NSTextAttachmentViewProvider behaviors differ across releases — I tested on macOS 26.4 with TextKit 2.

  6. A small Xcode project that reproduces the behavior, if you can put one together. It doesn't need to be your full editor — even a single text view with one custom attachment subclass would let me see what's different from my repro. Given that five plausible causes don't reproduce in my project, having yours that does would let me pinpoint the difference quickly.

Your "different paragraph types fine, same paragraph flickers" observation strongly suggests paragraph-level relayout is the trigger — typing in the same paragraph forces that paragraph to re-layout, which is when the attachment view gets requeried. The remaining question is what specifically about your code makes that requery destructive instead of seamless.

Thanks for posting. I built a minimal test to try to reproduce this — a SwiftUI NSViewRepresentable-wrapped NSTextView with a custom NSTextAttachment subclass and a viewProvider returning a custom NSView. I then stress-tested it against five plausible causes, and none of them reproduced any flicker:

  1. Baseline pattern — custom attachment + view provider returning a tinted layer-backed view, type in the same paragraph as the inserted attachment: stable.
  2. No caching in loadView() — every call constructs a brand-new NSView with fresh subviews and constraints: stable.
  3. Aggressive layout invalidation on every keystrokeNSTextLayoutManager.invalidateLayout(for: documentRange) from a textDidChange: delegate: stable.
  4. Mixed content sources — both attachment.image set to a programmatically drawn NSImage and a custom viewProvider returning a separate NSView: stable.
  5. Raster image contentloadView() returns an NSView containing an NSImageView with a real NSBitmapImageRep-backed NSImage instead of a layer-tinted plain view: stable.

That tells me the flicker isn't in any of the most common anti-patterns — it's something specific to your implementation that I haven't anticipated. To narrow it down, could you share the following?

  1. Your ImageAttachment class, including:

    • The viewProvider(for:location:textContainer:) override
    • The NSTextAttachmentViewProvider.loadView() implementation
    • Whatever you mean by "attachmentView" — is that a property you added to your subclass, or are you setting attachment.image, or something else? The exact wiring matters here.
  2. Your NSViewRepresentable (or NSTextView-wrapping code), especially:

    • Any NSTextViewDelegate methods you implement
    • Any textStorageDidProcessEditing: / textDidChange: handlers
    • Any code that re-applies attributes after a text change (for example, syntax highlighting, autocomplete, or formatting updates)
    • Whether you ever call addSubview on the attachment view yourself, rather than letting the framework manage its placement.
  3. Whether you have a custom NSTextStorage subclass. If your storage's processEditing reapplies attributes (including the attachment) on every edit, that could trigger the framework to requery the view.

  4. How your image loads. Is it always available synchronously by the time loadView() runs, or is there an async fetch (network, disk, render queue) that makes the image briefly unavailable on each load? An async load on every paragraph relayout would look exactly like flicker.

  5. macOS version you're targeting and testing on. The TextKit 2 vs TextKit 1 default and several NSTextAttachmentViewProvider behaviors differ across releases — I tested on macOS 26.4 with TextKit 2.

  6. A small Xcode project that reproduces the behavior, if you can put one together. It doesn't need to be your full editor — even a single text view with one custom attachment subclass would let me see what's different from my repro. Given that five plausible causes don't reproduce in my project, having yours that does would let me pinpoint the difference quickly.

Your "different paragraph types fine, same paragraph flickers" observation strongly suggests paragraph-level relayout is the trigger — typing in the same paragraph forces that paragraph to re-layout, which is when the attachment view gets requeried. The remaining question is what specifically about your code makes that requery destructive instead of seamless.

NSTextAttachment view flicker while typing in same paragraph
 
 
Q