Skip to content

iOS 26: partial-alpha NSColor in setAttributedText renders zero glyphs on plain UILabel/UIButton #1107

@proggeramlug

Description

@proggeramlug

Summary

On iOS 26.5 device (not iOS 17 simulator), plain Text(...) + textSetFontSize + textSetColor with an alpha < 1.0 color renders zero glyphs. The widget is sized correctly and the layout reserves space, but no text is painted. Same regression affects Button(...) titles styled via textSetColor on UIButton.

AttributedText(...) + attributedTextAppend(...) is unaffected — text with the same partial-alpha color renders correctly.

Reproducible scenario

import { Text, VStack, textSetFontSize, textSetColor } from \"perry/ui\";

const TEXT_PRIMARY = { r: 0, g: 0, b: 0, a: 0.87 }; // Material 87% black

const slogan = Text(\"Erlebe eine Welt, in der Teilen Freude schenkt\");
textSetFontSize(slogan, 24);
textSetColor(slogan, TEXT_PRIMARY.r, TEXT_PRIMARY.g, TEXT_PRIMARY.b, TEXT_PRIMARY.a);

Build: `perry compile src/main.ts --target ios`, deploy to iOS 26.5 device.
Result: the slogan label has correct intrinsic size (verified by setting a sentinel background color), but no glyphs are visible.

Hardcoding the same RGB with alpha = 1.0 in perry-ui-ios::widgets::text::set_color (or via a custom test) renders correctly. Hardcoding (1, 0, 0, 1.0) renders bright red text as expected. Only alpha < 1.0 triggers the regression.

What I tried (perry-ui-ios runtime)

  1. Routing text::set_font_size / set_font_weight / set_color through setAttributedText: with NSColor in the attributes dict — same \"NSFont\" / \"NSColor\" keys as attributed_text.rs, same colorWithRed:green:blue:alpha: UIColor. Still zero-glyph for alpha < 1.
  2. Setting numberOfLines: 0 + lineBreakMode: 0 before setAttributedText:. No change.
  3. Matching AttributedText's exact path: build an immutable piece via initWithString:attributes:, append to a fresh NSMutableAttributedString buffer, setAttributedText: with the buffer. Still invisible.
  4. Skipping setText: in text::create entirely and routing initial text through setAttributedText: (so the label is on the attributed path from the start). Still invisible.
  5. Clearing via setText:@\"\" before setAttributedText: to invalidate cached glyph metrics. Still invisible.
  6. Forcing alpha = 1.0 in the runtime: works. Text is visible (in pure black instead of designed 87% gray).

So the trigger is consistently a partial-alpha NSColor in the attributes dict applied via setAttributedText: on a plain UILabel. Why AttributedText widget's identical-looking code path is immune, I could not pin down.

Environment

Workarounds

  • Use AttributedText widget for any user-visible styled text targeting iOS 26 device.
  • Or pin all text colors to alpha: 1.0 in theme.ts (loses the Material 87% / 60% gray distinction).

Happy to provide minimal repro project / additional diagnostics. Suspect this is related to the iOS 26 "Liquid Glass" changes to UIKit text rendering.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions