Post

Replies

Boosts

Views

Activity

Reply to NSJSONSerialization silently drops U+FEFF from JSON string content — keys merge, characters vanish
Thanks for the pointer — we'll engage with the Swift Forums thread for the Swift side. For our Objective-C project we've decided to sidestep the issue entirely by switching to yyjson, a spec-compliant C parser. It's MIT-licensed, header-only, and fully testable — and it just does the right thing with U+FEFF. Probably the cleanest resolution for native code anyway. Thanks again for your time and for the Swift Forums tip! Best, Kolja
Topic: App & System Services SubTopic: General Tags:
Jun ’26
Reply to NSJSONSerialization silently drops U+FEFF from JSON string content — keys merge, characters vanish
Hi Quinn, Thanks so much for looking at this — really appreciate it! We stumbled onto the bug while building a local LLM inference engine for macOS. We load Gemma-4's tokenizer vocabulary from a tokenizer.json file, and some of the vocab keys contain U+FEFF — for example "<U+FEFF>#". When we parsed the file through NSJSONSerialization, those keys silently collapsed onto their BOM-less twins, overwriting the correct token IDs. The model then produced garbage output and it took a while to track down why. We've worked around it on our end with a sentinel-swap before parsing, so we're not blocked — we're reporting it because it seems like the kind of silent data corruption that could surprise other developers and be very hard to diagnose. As for whether it's a regression: you're in a much better position to answer that than we are since you have the source history. We'd love to know either way. Happy to provide any additional repro material if it helps. Best, Kolja
Topic: App & System Services SubTopic: General Tags:
Jun ’26
Reply to TextKit 2 + SwiftUI (NSViewRepresentable): NSTextLayoutManager rendering attributes don’t reliably draw/update
Thanks Ziqiao — this matches what I landed on. I ran into these same challenges building my own TextKit 2-based editor and ended up on exactly the display-attributes approach you describe (NSTextContentStorageDelegate.textContentStorage(_:textParagraphWith:) returning an NSTextParagraph with resolved attributes, backing store left untouched). It's solid and the per-paragraph performance is fine. One thing worth adding for anyone finding this thread: the delegate is re-invoked automatically when a paragraph is edited, which is perfect for syntax highlighting (appearance is a function of the text). But if your highlight changes without a text edit — Dark Mode, Dynamic Type, a search/selection-driven highlight — nothing re-vends the paragraph and it goes stale. The fix that's been reliable for me is to change the input my resolver reads, then call invalidateLayoutForRange: on the affected range (scope it to the paragraph for per-keystroke changes; whole document is fine for rare global changes like trait changes). Notably, invalidateLayoutForRange: does re-trigger the content-storage delegate, even though invalidateRenderingAttributes(for:) doesn't redraw — which lines up with the rendering-attributes bug you confirmed; the layout-invalidation route is the one that works. Full working example if it's useful: TextKit2-Editor: see SXTextStorageDelegate (the vending) and handleTraitChange in SXTextViewController (the forced re-vend).
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’26
Reply to UITextView for displaying long text?
Yes — this is exactly what TextKit 2 was built for, and it largely retires the custom UIScrollView + tile-rendering approach. Since iOS 15, UITextView is backed by TextKit 2 (NSTextLayoutManager) by default. The key piece for your case is NSTextViewportLayoutController: TextKit 2 lays out only the text fragments inside the visible viewport (plus a small over-scroll margin), not the whole document. So a long chapter doesn't get laid out up front, and you're no longer fighting the old coordinate ceiling the way TextKit 1 / a single giant canvas did. You get selection handles, the loupe, link interaction, Dynamic Type, etc. for free, because it's a real UITextView. One important gotcha: a UITextView only stays on TextKit 2 if you never touch the legacy NSLayoutManager. Accessing the .layoutManager property triggers an automatic, permanent downgrade to TextKit 1 (and you lose viewport layout). Use .textLayoutManager / .textContentManager instead, or create it explicitly with init(usingTextLayoutManager: true). For truly book-length (not chapter-length) content you may still segment documents, but for a scrolling chapter a TextKit 2 text view should handle it smoothly without the custom scroll plumbing. If it helps to see the moving parts in a real project, I recently open-sourced a TextKit 2 editor in Objective-C — it leans on the resolve-at-render / viewport model and might save you some spelunking: TextKit2-Editor
Topic: UIKit SubTopic:
UIKit Q&A
Jun ’26
Reply to NSJSONSerialization silently drops U+FEFF from JSON string content — keys merge, characters vanish
Thanks for the pointer — we'll engage with the Swift Forums thread for the Swift side. For our Objective-C project we've decided to sidestep the issue entirely by switching to yyjson, a spec-compliant C parser. It's MIT-licensed, header-only, and fully testable — and it just does the right thing with U+FEFF. Probably the cleanest resolution for native code anyway. Thanks again for your time and for the Swift Forums tip! Best, Kolja
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jun ’26
Reply to NSJSONSerialization silently drops U+FEFF from JSON string content — keys merge, characters vanish
Hi Quinn, Thanks so much for looking at this — really appreciate it! We stumbled onto the bug while building a local LLM inference engine for macOS. We load Gemma-4's tokenizer vocabulary from a tokenizer.json file, and some of the vocab keys contain U+FEFF — for example "<U+FEFF>#". When we parsed the file through NSJSONSerialization, those keys silently collapsed onto their BOM-less twins, overwriting the correct token IDs. The model then produced garbage output and it took a while to track down why. We've worked around it on our end with a sentinel-swap before parsing, so we're not blocked — we're reporting it because it seems like the kind of silent data corruption that could surprise other developers and be very hard to diagnose. As for whether it's a regression: you're in a much better position to answer that than we are since you have the source history. We'd love to know either way. Happy to provide any additional repro material if it helps. Best, Kolja
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jun ’26
Reply to TextKit 2 + SwiftUI (NSViewRepresentable): NSTextLayoutManager rendering attributes don’t reliably draw/update
Thanks Ziqiao — this matches what I landed on. I ran into these same challenges building my own TextKit 2-based editor and ended up on exactly the display-attributes approach you describe (NSTextContentStorageDelegate.textContentStorage(_:textParagraphWith:) returning an NSTextParagraph with resolved attributes, backing store left untouched). It's solid and the per-paragraph performance is fine. One thing worth adding for anyone finding this thread: the delegate is re-invoked automatically when a paragraph is edited, which is perfect for syntax highlighting (appearance is a function of the text). But if your highlight changes without a text edit — Dark Mode, Dynamic Type, a search/selection-driven highlight — nothing re-vends the paragraph and it goes stale. The fix that's been reliable for me is to change the input my resolver reads, then call invalidateLayoutForRange: on the affected range (scope it to the paragraph for per-keystroke changes; whole document is fine for rare global changes like trait changes). Notably, invalidateLayoutForRange: does re-trigger the content-storage delegate, even though invalidateRenderingAttributes(for:) doesn't redraw — which lines up with the rendering-attributes bug you confirmed; the layout-invalidation route is the one that works. Full working example if it's useful: TextKit2-Editor: see SXTextStorageDelegate (the vending) and handleTraitChange in SXTextViewController (the forced re-vend).
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Jun ’26
Reply to UITextView for displaying long text?
Yes — this is exactly what TextKit 2 was built for, and it largely retires the custom UIScrollView + tile-rendering approach. Since iOS 15, UITextView is backed by TextKit 2 (NSTextLayoutManager) by default. The key piece for your case is NSTextViewportLayoutController: TextKit 2 lays out only the text fragments inside the visible viewport (plus a small over-scroll margin), not the whole document. So a long chapter doesn't get laid out up front, and you're no longer fighting the old coordinate ceiling the way TextKit 1 / a single giant canvas did. You get selection handles, the loupe, link interaction, Dynamic Type, etc. for free, because it's a real UITextView. One important gotcha: a UITextView only stays on TextKit 2 if you never touch the legacy NSLayoutManager. Accessing the .layoutManager property triggers an automatic, permanent downgrade to TextKit 1 (and you lose viewport layout). Use .textLayoutManager / .textContentManager instead, or create it explicitly with init(usingTextLayoutManager: true). For truly book-length (not chapter-length) content you may still segment documents, but for a scrolling chapter a TextKit 2 text view should handle it smoothly without the custom scroll plumbing. If it helps to see the moving parts in a real project, I recently open-sourced a TextKit 2 editor in Objective-C — it leans on the resolve-at-render / viewport model and might save you some spelunking: TextKit2-Editor
Topic: UIKit SubTopic:
UIKit Q&A
Replies
Boosts
Views
Activity
Jun ’26