Skip to content

[iOS] Fix Picker CharacterSpacing lost after item selection when Title is set#34974

Merged
kubaflo merged 2 commits into
dotnet:inflight/currentfrom
SyedAbdulAzeemSF4852:fix/picker-charspacing-lost-on-select
May 12, 2026
Merged

[iOS] Fix Picker CharacterSpacing lost after item selection when Title is set#34974
kubaflo merged 2 commits into
dotnet:inflight/currentfrom
SyedAbdulAzeemSF4852:fix/picker-charspacing-lost-on-select

Conversation

@SyedAbdulAzeemSF4852
Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Issue Details

  • When a Picker has both a Title and a non-zero CharacterSpacing, the character spacing is silently lost as soon as the user selects an item from the picker, or when SelectedIndex is changed programmatically. The spacing is visible before selection (applied to the placeholder/title text), but after any item is selected, the selected item renders without spacing.

Root Cause

  • Regression: Introduced by PR [iOS] Fixed picker title's color #20205
  • PR [iOS] Fixed picker title's color #20205 changed iOS Picker to apply CharacterSpacing via AttributedPlaceholder so the Title text respects kern. When the user selects an item, the code assigns a plain string to platformPicker.Text. iOS internally creates a zero-kern AttributedText from that plain string and simultaneously hides AttributedPlaceholder, since iOS never shows a placeholder when the text field has a value. This means the kern that was applied to the placeholder is gone, and no kern is applied to the selected item text — resulting in CharacterSpacing being silently lost after selection.

Description of Change

  • After platformPicker.Text is set to the selected item's string, UpdateCharacterSpacing is now explicitly called to re-apply kern to AttributedText. This is done in two places: in UpdatePickerFromPickerSource (the Done-button code path in PickerHandler.iOS.cs) and in UpdatePicker (the programmatic SelectedIndex change path in PickerExtensions.cs), ensuring CharacterSpacing survives item selection regardless of how the selection is triggered.

Issues Fixed

Fixes #34971

Validated the behaviour in the following platforms

  • Windows
  • Android
  • iOS
  • Mac

Output

Before After
Before.mov
After.mov

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 15, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34974

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34974"

@dotnet-policy-service dotnet-policy-service Bot added community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Apr 15, 2026
@sheiksyedm sheiksyedm marked this pull request as ready for review April 15, 2026 10:57
Copilot AI review requested due to automatic review settings April 15, 2026 10:57
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes an iOS/MacCatalyst regression where Picker.CharacterSpacing is lost after an item is selected when Title is set, by re-applying kerning after the native text is assigned.

Changes:

  • Re-apply CharacterSpacing after platformPicker.Text is set during selection updates (both programmatic and “Done” selection paths).
  • Add an iOS device test to validate CharacterSpacing is preserved across SelectedIndex updates.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/Core/tests/DeviceTests/Handlers/Picker/PickerHandlerTests.iOS.cs Adds a device test asserting character spacing is preserved when SelectedIndex changes programmatically.
src/Core/src/Platform/iOS/PickerExtensions.cs Ensures UpdatePicker always re-applies character spacing after setting Text.
src/Core/src/Handlers/Picker/PickerHandler.iOS.cs Re-applies character spacing after assigning Text in the “Done button” selection flow.

@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Apr 15, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 15, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 15, 2026
Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please try the ai's suggestions?

@dotnet dotnet deleted a comment from MauiBot Apr 23, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 23, 2026
@MauiBot MauiBot added s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR labels Apr 23, 2026
PureWeen pushed a commit that referenced this pull request Apr 30, 2026
…ability (#35133)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

> **Depends on #35136** (pipeline category detection — should merge
first)

## What this does

Two things:

### 1. UI test category detection in PR review

During the PR review workflow, Step 0.5 detects which UI test categories
the PR impacts and writes the result to the AI summary comment. This
gives reviewers visibility into which UI tests are relevant.

**Detection** reuses the 3-tier script from #35136 (test attributes →
source paths → AI reasoning).

**AI summary** shows a new 🧪 UI Tests section with detected categories
before the gate section.

### 2. Gate reliability fixes

Multiple fixes to make the gate (`verify-tests-fail.ps1`) more
deterministic:

| Fix | Problem it solves |
|-----|-------------------|
| **Absolute path resolution** | Gate scripts not found on Linux CI
agents (`Resolve-Path`, `GetFullPath`) |
| **File existence check** | Instant cryptic failure when verify script
is missing — now logs clear error |
| **3x retry on ENV ERROR** | Emulator timeouts, ADB failures, app
crashes — transient issues that pass on retry |
| **Strip bad report blocks** | Old verify script produces `Passed:
False` with empty counts — stripped instead of shown |
| **Gate log in fallback** | When report is missing, shows last 20 lines
of gate output instead of just `❌ FAILED / Platform: IOS` |

## Files

| File | Changes |
|------|---------|
| `.github/scripts/Review-PR.ps1` | Step 0.5 category detection + all 5
gate fixes |
| `.github/scripts/post-ai-summary-comment.ps1` | Add `uitests` phase to
render detected categories |
| `.github/pr-review/pr-preflight.md` | Step 7: AI identifies impacted
UI test categories |

## Validation — PR reviewer builds (Apr 26)

10 builds against real PRs — all succeeded ✅. Category detection shown
in AI summary comment.

| PR | Categories Detected | Build | AI Summary |
|----|-------------------|-------|------------|
| #35037 (WebView theme) | `ViewBaseTests,WebView` |
[13940071](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940071)
|
[comment](#35037 (comment))
|
| #35031 (Shell memory leak) | `Shell` |
[13940072](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940072)
|
[comment](#35031 (comment))
|
| #35020 (XAML Hot Reload) | _(none — XAML only)_ |
[13940073](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940073)
| ✅ Shows "No UI test categories" |
| #35008 (Shell SearchHandler) | `Shell` |
[13940074](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940074)
| ✅ |
| #34997 (RadioButton gradient) | `RadioButton,ViewBaseTests` |
[13940075](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940075)
| ✅ |
| #34980 (DatePicker rotation) | `ViewBaseTests` |
[13940076](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940076)
| ✅ |
| #34974 (Picker CharacterSpacing) | `ViewBaseTests` |
[13940077](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940077)
| ✅ |
| #34923 (SwipeView threshold) | `SwipeView,ViewBaseTests` |
[13940078](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940078)
| ✅ |
| #34907 (CollectionView ScrollTo) | `CollectionView` |
[13940079](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940079)
| ✅ |
| #34845 (RefreshView binding) | `RefreshView,ViewBaseTests` |
[13940080](https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=13940080)
| ✅ |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet dotnet deleted a comment from MauiBot May 2, 2026
Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expert Review — 1 findings

See inline comments for details.

@dotnet dotnet deleted a comment from MauiBot May 3, 2026
@dotnet dotnet deleted a comment from MauiBot May 3, 2026
MauiBot
MauiBot previously requested changes May 3, 2026
Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Automated review — alternative fix proposed

The expert-reviewer evaluation compared the PR fix against #1 automatically generated candidates and selected try-fix-1 as the strongest fix.

Why: try-fix-1 passed all 4 regression tests empirically using a SetTextWithCharacterSpacing helper that atomically constructs NSAttributedString with KerningAdjustment instead of the PR's fragile read-modify-write pattern. It also covers the OnEditing handler gap the PR missed and avoids the MacCatalyst test crash entirely.

Please consider applying the candidate diff below (or use it as guidance). Once you push an update, this workflow will re-trigger and re-evaluate.

Candidate diff (`try-fix-1`)
diff --git a/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs b/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs
index a54299d290..11fe557578 100644
--- a/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs
+++ b/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs
@@ -255,7 +255,7 @@ namespace Microsoft.Maui.Handlers
 			if (VirtualView == null || PlatformView == null || pickerSource == null)
 				return;
 
-			PlatformView.Text = VirtualView.GetItem(pickerSource.SelectedIndex);
+			PlatformView.SetTextWithCharacterSpacing(VirtualView.GetItem(pickerSource.SelectedIndex), VirtualView.CharacterSpacing);
 			VirtualView.SelectedIndex = pickerSource.SelectedIndex;
 		}
 
@@ -423,7 +423,7 @@ namespace Microsoft.Maui.Handlers
 				// Reset the TextField's Text so it appears as if typing with a keyboard does not work.
 				var selectedIndex = virtualView.SelectedIndex;
 
-				platformView.Text = virtualView.GetItem(selectedIndex);
+				platformView.SetTextWithCharacterSpacing(virtualView.GetItem(selectedIndex), virtualView.CharacterSpacing);
 
 				// Also clears the undo stack (undo/redo possible on iPads)
 				platformView.UndoManager?.RemoveAllActions();
diff --git a/src/Core/src/Platform/iOS/PickerExtensions.cs b/src/Core/src/Platform/iOS/PickerExtensions.cs
index c2de04d1fd..13e429ae28 100644
--- a/src/Core/src/Platform/iOS/PickerExtensions.cs
+++ b/src/Core/src/Platform/iOS/PickerExtensions.cs
@@ -1,6 +1,7 @@
 #nullable enable
 using System;
 using Foundation;
+using UIKit;
 
 namespace Microsoft.Maui.Platform
 {
@@ -36,18 +37,45 @@ namespace Microsoft.Maui.Platform
 			platformPicker.UpdateAttributedPlaceholder(new NSAttributedString(picker.Title ?? string.Empty, null, picker?.TitleColor?.ToPlatform()));
 		}
 
+		/// <summary>
+		/// Sets text on a picker using AttributedText with kern to avoid iOS clearing
+		/// character spacing when plain Text is assigned.
+		/// </summary>
+		/// <remarks>
+		/// Unlike UpdateCharacterSpacing (which reads back AttributedText and adds kern),
+		/// this creates a fresh NSAttributedString to work around an iOS issue where
+		/// reading AttributedText immediately after setting Text doesn't reliably
+		/// preserve kern in all handler lifecycle contexts.
+		/// </remarks>
+		internal static void SetTextWithCharacterSpacing(this MauiPicker platformPicker, string text, double characterSpacing)
+		{
+			if (characterSpacing == 0)
+			{
+				platformPicker.Text = text;
+				return;
+			}
+
+			var attributes = new UIKit.UIStringAttributes
+			{
+				KerningAdjustment = (float)characterSpacing
+			};
+			platformPicker.AttributedText = new NSAttributedString(text ?? string.Empty, attributes);
+		}
+
 		internal static void UpdatePicker(this MauiPicker platformPicker, IPicker picker, int? newSelectedIndex = null)
 		{
 			var selectedIndex = newSelectedIndex ?? picker.SelectedIndex;
 
 			if (selectedIndex != -1)
 			{
-				platformPicker.Text = picker.GetItem(selectedIndex);
+				platformPicker.SetTextWithCharacterSpacing(picker.GetItem(selectedIndex), picker.CharacterSpacing);
 			}
 			else
 			{
 				platformPicker.Text = null;
 				platformPicker.UpdatePickerTitle(picker);
+				// Applies character spacing to the placeholder when no item is selected
+				platformPicker.UpdateCharacterSpacing(picker);
 			}
 
 			var pickerView = platformPicker.UIPickerView;

@dotnet dotnet deleted a comment from MauiBot May 8, 2026
@kubaflo kubaflo dismissed MauiBot’s stale review May 8, 2026 01:22

Resetting for re-review

Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expert Review — 4 findings

See inline comments for details.

// Re-apply kern: plain Text assignment above clears iOS kern attributes.
PlatformView.UpdateCharacterSpacing(VirtualView);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[info] Handler Mapper / Complexity Reduction — Setting VirtualView.SelectedIndex on line 259 fires the bindable-property change notification, which routes through MapSelectedIndexUpdateSelectedIndexUpdatePicker (which now itself calls UpdateCharacterSpacing thanks to the change in PickerExtensions.cs:53). So when the index actually changes, this call duplicates the work done by the mapper.

It is not fully redundant when the user taps Done without changing selection (no property-change → no mapper fires, but PlatformView.Text = ... on line 258 still re-runs and clears kerning). Keeping the explicit call is defensible as belt-and-braces; just note the duplication for the common path. If you want a single source of truth, you could drop line 261 and rely on the extension, but that would silently lose kerning in the unchanged-selection edge case — so leaving it as-is is the safer choice. No change required.

platformPicker.UpdatePickerTitle(picker);
}

platformPicker.UpdateCharacterSpacing(picker);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[info] Cross-Platform Consistency — Verified this matches the established sibling pattern: DatePickerExtensions.cs:116 and TimePickerExtensions.cs:89 both call UpdateCharacterSpacing(...) immediately after assigning .Text. Picker now joins that pattern. The placement (after both branches of the if/else, before ReloadAllComponents) correctly handles both the selected-item case (kerns AttributedText) and the no-selection/title case (kerns AttributedPlaceholder, since UpdateCharacterSpacing on UITextField updates both, and the null-conditional in TextFieldExtensions.cs:133-139 makes it safe when AttributedText is null). No change required.

@MauiBot MauiBot added s/agent-review-incomplete and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues labels May 8, 2026
@dotnet dotnet deleted a comment from MauiBot May 11, 2026
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented May 11, 2026

🤖 AI Summary

👋 @SyedAbdulAzeemSF4852 — new AI review results are available. Please review the latest session below.

📊 Review Sessionaa694be · Address review feedback: array initializer + Done-button device test · 2026-05-11 22:05 UTC
🚦 Gate — Test Before & After Fix

Gate Result: ✅ PASSED

Platform: IOS · Base: main · Merge base: f8cb875e

Test Without Fix (expect FAIL) With Fix (expect PASS)
📱 PickerHandlerTests (SelectedIndexDoesNotAffectCharacterSpacing, SelectingItemWithDoneDoesNotAffectCharacterSpacing) Category=Picker ✅ FAIL — 388s ✅ PASS — 230s
🔴 Without fix — 📱 PickerHandlerTests (SelectedIndexDoesNotAffectCharacterSpacing, SelectingItemWithDoneDoesNotAffectCharacterSpacing): FAIL ✅ · 388s

(truncated to last 15,000 chars)

ectly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.0574950] 2026-05-11 14:19:18.057180-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] ContainerView Adds And Removes
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.0633670] 2026-05-11 14:19:18.063067-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Transformation Calculated Correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.0688610] 2026-05-11 14:19:18.068610-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Automation Id is set correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.0750340] 2026-05-11 14:19:18.074757-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Updating Text Does Not Affect HorizontalTextAlignment
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.0778500] 2026-05-11 14:19:18.077502-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Updating Text Does Not Affect HorizontalTextAlignment
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.0846870] 2026-05-11 14:19:18.084377-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Text Color Initializes Correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.0893640] 2026-05-11 14:19:18.089041-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] ContainerView Remains If Shadow Mapper Runs Again
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.0932210] 2026-05-11 14:19:18.092955-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Native View Bounds are not empty
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.0957960] 2026-05-11 14:19:18.095545-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Native View Bounds are not empty
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.1059080] 2026-05-11 14:19:18.105637-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Native View Bounds are not empty
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.3344710] 2026-05-11 14:19:18.334095-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Semantic Heading is set correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.3662170] 2026-05-11 14:19:18.365933-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Background Initializes Correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.3792630] 2026-05-11 14:19:18.378944-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Background Initializes Correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.3878760] 2026-05-11 14:19:18.387615-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Background Initializes Correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.3947990] 2026-05-11 14:19:18.394491-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Semantic Description is set correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4038150] 2026-05-11 14:19:18.403494-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Opacity is set correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4082480] 2026-05-11 14:19:18.407965-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Opacity is set correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4128920] 2026-05-11 14:19:18.412486-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Opacity is set correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4166470] 2026-05-11 14:19:18.416260-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Opacity is set correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4198320] 2026-05-11 14:19:18.419540-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] 	[PASS] Opacity is set correctly
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4200370] 2026-05-11 14:19:18.419858-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] Microsoft.Maui.DeviceTests.PickerHandlerTests 1.3380399 ms
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4241960] 2026-05-11 14:19:18.423881-0700 Microsoft.Maui.Core.DeviceTests[6869:46731] Failed tests:
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4245400] 2026-05-11 14:19:18.424288-0700 Microsoft.Maui.Core.DeviceTests[6869:46731] 1) 	[FAIL] Updating SelectedIndex Does Not Affect CharacterSpacing   Test name: Updating SelectedIndex Does Not Affect CharacterSpacing(initialIndex: 0, newIndex: 1)   Test case: Updating SelectedIndex Does Not Affect CharacterSpacing
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4246090] 2026-05-11 14:19:18.424435-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    Assembly:  [Microsoft.Maui.Core.DeviceTests, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4246340]    Exception messages: Assert.Equal() Failure: Values differ
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4246400] Expected: 4
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4247250] 2026-05-11 14:19:18.424573-0700 Microsoft.Maui.Core.DeviceTests[6869:46731] Actual:   0   Exception stack traces:    at Microsoft.Maui.DeviceTests.PickerHandlerTests.<>c__DisplayClass8_0.<SelectedIndexDoesNotAffectCharacterSpacing>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4247410]    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass1_0.<DispatchAsync>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4248300] 2026-05-11 14:19:18.424694-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass0_0`1[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].<DispatchAsync>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4248470] --- End of stack trace from previous location ---
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4249300] 2026-05-11 14:19:18.424798-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    at Microsoft.Maui.DeviceTests.PickerHandlerTests.SelectedIndexDoesNotAffectCharacterSpacing(Int32 initialIndex, Int32 newIndex)
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4249370] --- End of stack trace from previous location ---
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4249400]    Execution time: 0.0170915
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4249440]    Test trait name: Category
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4249470]       value: Picker
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4251530] 2026-05-11 14:19:18.424901-0700 Microsoft.Maui.Core.DeviceTests[6869:46731] 2) 	[FAIL] Updating SelectedIndex Does Not Affect CharacterSpacing   Test name: Updating SelectedIndex Does Not Affect CharacterSpacing(initialIndex: 1, newIndex: 0)   Test case: Updating SelectedIndex Does Not Affect CharacterSpacing
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4251670] 2026-05-11 14:19:18.424997-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    Assembly:  [Microsoft.Maui.Core.DeviceTests, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4251710]    Exception messages: Assert.Equal() Failure: Values differ
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4251740] Expected: 4
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4253850] 2026-05-11 14:19:18.425084-0700 Microsoft.Maui.Core.DeviceTests[6869:46731] Actual:   0   Exception stack traces:    at Microsoft.Maui.DeviceTests.PickerHandlerTests.<>c__DisplayClass8_0.<SelectedIndexDoesNotAffectCharacterSpacing>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4254160]    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass1_0.<DispatchAsync>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4254250] 2026-05-11 14:19:18.425203-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass0_0`1[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].<DispatchAsync>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4254300] --- End of stack trace from previous location ---
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4254370] 2026-05-11 14:19:18.425277-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    at Microsoft.Maui.DeviceTests.PickerHandlerTests.SelectedIndexDoesNotAffectCharacterSpacing(Int32 initialIndex, Int32 newIndex)
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4254410] --- End of stack trace from previous location ---
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4254440]    Execution time: 0.0078849
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4254470]    Test trait name: Category
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4254490]       value: Picker
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4255950] 2026-05-11 14:19:18.425419-0700 Microsoft.Maui.Core.DeviceTests[6869:46731] 3) 	[FAIL] Selecting An Item With Done Keeps CharacterSpacing   Test name: Selecting An Item With Done Keeps CharacterSpacing(initialIndex: 1, newIndex: 0)   Test case: Selecting An Item With Done Keeps CharacterSpacing
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4256840] 2026-05-11 14:19:18.425536-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    Assembly:  [Microsoft.Maui.Core.DeviceTests, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4256980]    Exception messages: Assert.Equal() Failure: Values differ
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4257020] Expected: 4
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4257870] 2026-05-11 14:19:18.425627-0700 Microsoft.Maui.Core.DeviceTests[6869:46731] Actual:   0   Exception stack traces:    at Microsoft.Maui.DeviceTests.PickerHandlerTests.<>c__DisplayClass9_0.<SelectingItemWithDoneDoesNotAffectCharacterSpacing>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4257990]    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass1_0.<DispatchAsync>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4258550] 2026-05-11 14:19:18.425718-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass0_0`1[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].<DispatchAsync>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4258610] --- End of stack trace from previous location ---
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4259700] 2026-05-11 14:19:18.425807-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    at Microsoft.Maui.DeviceTests.PickerHandlerTests.SelectingItemWithDoneDoesNotAffectCharacterSpacing(Int32 initialIndex, Int32 newIndex)
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4259850] --- End of stack trace from previous location ---
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4259890]    Execution time: 0.0094259
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4259920]    Test trait name: Category
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4259950]       value: Picker
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4261580] 2026-05-11 14:19:18.425998-0700 Microsoft.Maui.Core.DeviceTests[6869:46731] 4) 	[FAIL] Selecting An Item With Done Keeps CharacterSpacing   Test name: Selecting An Item With Done Keeps CharacterSpacing(initialIndex: 0, newIndex: 1)   Test case: Selecting An Item With Done Keeps CharacterSpacing
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4262990] 2026-05-11 14:19:18.426118-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    Assembly:  [Microsoft.Maui.Core.DeviceTests, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4263260]    Exception messages: Assert.Equal() Failure: Values differ
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4263300] Expected: 4
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4263790] 2026-05-11 14:19:18.426200-0700 Microsoft.Maui.Core.DeviceTests[6869:46731] Actual:   0   Exception stack traces:    at Microsoft.Maui.DeviceTests.PickerHandlerTests.<>c__DisplayClass9_0.<SelectingItemWithDoneDoesNotAffectCharacterSpacing>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4263870]    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass1_0.<DispatchAsync>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4264660] 2026-05-11 14:19:18.426304-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    at Microsoft.Maui.Dispatching.DispatcherExtensions.<>c__DisplayClass0_0`1[[System.Boolean, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].<DispatchAsync>b__0()
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4264740] --- End of stack trace from previous location ---
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4265310] 2026-05-11 14:19:18.426423-0700 Microsoft.Maui.Core.DeviceTests[6869:46731]    at Microsoft.Maui.DeviceTests.PickerHandlerTests.SelectingItemWithDoneDoesNotAffectCharacterSpacing(Int32 initialIndex, Int32 newIndex)
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4265430] --- End of stack trace from previous location ---
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4265460]    Execution time: 0.009578
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4265490]    Test trait name: Category
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4265530]       value: Picker
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4270600] 2026-05-11 14:19:18.426902-0700 Microsoft.Maui.Core.DeviceTests[6869:46731] Tests run: 93 Passed: 88 Inconclusive: 0 Failed: 4 Ignored: 1
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4323420] 2026-05-11 14:19:18.432068-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] Xml file was written to the provided writer.
�[40m�[37mdbug�[39m�[22m�[49m: [14:19:18.4325270] 2026-05-11 14:19:18.432317-0700 Microsoft.Maui.Core.DeviceTests[6869:46240] Tests run: 1170 Passed: 88 Inconclusive: 0 Failed: 4 Ignored: 1078
�[40m�[37mdbug�[39m�[22m�[49m: ==================== End of ApplicationLog ====================
�[40m�[37mdbug�[39m�[22m�[49m: 
�[40m�[32minfo�[39m�[22m�[49m: Uninstalling the application 'com.microsoft.maui.core.devicetests' from 'iPhone 11 Pro'
�[40m�[37mdbug�[39m�[22m�[49m: 
�[40m�[37mdbug�[39m�[22m�[49m: Running /Applications/Xcode_26.0.1.app/Contents/Developer/usr/bin/simctl
�[40m�[37mdbug�[39m�[22m�[49m: Process simctl exited with 0
�[40m�[32minfo�[39m�[22m�[49m: Application 'com.microsoft.maui.core.devicetests' was uninstalled successfully
�[40m�[32minfo�[39m�[22m�[49m: <<XHARNESS_RESULT_START>>
      {
        "version": 1,
        "machineName": "PJC3Q2M0WF-1",
        "exitCode": 1,
        "exitCodeName": "TESTS_FAILED",
        "platform": "apple",
        "device": "iPhone 11 Pro",
        "deviceOsVersion": "26.0",
        "files": [
          {
            "name": "test-ios-simulator-64_26.0-37F44326-A7FB-4CF0-91E0-66F935BB1068.log",
            "type": "executionlog"
          },
          {
            "name": "list-ios-simulator-64_26.0-20260511_141842.log",
            "type": "devicelist"
          },
          {
            "name": "test-ios-simulator-64_26.0-20260511_141849.log",
            "type": "testlog"
          },
          {
            "name": "iPhone 11 Pro.log",
            "type": "systemlog"
          },
          {
            "name": "Microsoft.Maui.Core.DeviceTests.log",
            "type": "systemlog"
          },
          {
            "name": "com.microsoft.maui.core.devicetests.log",
            "type": "applicationlog"
          },
          {
            "name": "xunit-test-ios-simulator-64_26.0-20260511_141849.xml",
            "type": "xmllog"
          }
        ]
      }
      <<XHARNESS_RESULT_END>>
XHarness exit code: 1 (TESTS_FAILED)
  Passed: 0
  Failed: 0
  Tests completed with exit code: 1

🟢 With fix — 📱 PickerHandlerTests (SelectedIndexDoesNotAffectCharacterSpacing, SelectingItemWithDoneDoesNotAffectCharacterSpacing): PASS ✅ · 230s

(truncated to last 15,000 chars)

pplication/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : monoeg_g_log
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6569860] 	0x10c20e848 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : load_aot_module
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6569940] 	0x10c2e8618 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_load_from
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6569990] 	0x10c2e8134 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_open
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6570060] 	0x10c2e9454 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_open
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6580600] 	0x10be55ddc - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libxamarin-dotnet.dylib : xamarin_assembly_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6580810] 	0x10c2ea470 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : invoke_assembly_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6580880] 	0x10c2e73f8 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_byname
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6581330] 	0x10c2180b0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : load_image
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6581450] 	0x10c20e7e0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : load_aot_module
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6581510] 	0x10c2e8618 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_load_from
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6581550] 	0x10c2e8134 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_open
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6581700] 	0x10c2e9454 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_open
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6581770] 	0x10be55ddc - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libxamarin-dotnet.dylib : xamarin_assembly_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6581810] 	0x10c2ea470 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : invoke_assembly_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6581850] 	0x10c2e73f8 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_byname
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6582060] 	0x10c2180b0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : load_image
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6582290] 	0x10c20e7e0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : load_aot_module
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6582630] 	0x10c2e8618 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_load_from
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6582730] 	0x10c2e8134 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_open
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6583150] 	0x10c2e9454 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_open
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6583220] 	0x10be55ddc - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libxamarin-dotnet.dylib : xamarin_assembly_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6583260] 	0x10c2ea470 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : invoke_assembly_preload_hook
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6583320] 	0x10c2e73f8 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_assembly_request_byname
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6583440] 	0x10c2180b0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : load_image
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6583530] 	0x10c20e7e0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : load_aot_module
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6583580] 	0x10c212fac - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_aot_get_method
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6583630] 	0x10c197f3c - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_jit_compile_method_with_opt
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6583700] 	0x10c195cac - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_jit_runtime_invoke
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6583830] 	0x10c356910 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_runtime_invoke_checked
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6583920] 	0x10c309818 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : create_exception_two_strings
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6584760] 	0x10c30959c - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_exception_from_name_two_strings_checked
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6584950] 	0x10c2e396c - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_runtime_init_checked
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6585080] 	0x10c19563c - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mini_init
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6585860] 	0x10c1ecd1c - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libmonosgen-2.0.dylib : mono_jit_init
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6586020] 	0x10be55014 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libxamarin-dotnet.dylib : xamarin_bridge_initialize
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.6586080] 	0x10be561e8 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/libxamarin-dotnet.dylib : xamarin_main
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7248840] 	0x106db80d0 - /Users/cloudtest/Library/Developer/CoreSimulator/Devices/37F44326-A7FB-4CF0-91E0-66F935BB1068/data/Containers/Bundle/Application/E26A3C2C-BCA1-4175-84BA-77CF28277DEA/Microsoft.Maui.Core.DeviceTests.app/Microsoft.Maui.Core.DeviceTests : main
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7249100] 	0x10b9153d0 - Unknown
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7249180] 	0x10ba17da4 - Unknown
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7249230]
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7249290] =================================================================
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7249340] 	Basic Fault Address Reporting
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7249390] =================================================================
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7249480] Memory around native instruction pointer (0x10bd5888c):0x10bd5887c  c0 03 5f d6 c0 03 5f d6 10 29 80 d2 01 10 00 d4  .._..._..)......
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7250050] 0x10bd5888c  e3 00 00 54 fd 7b bf a9 fd 03 00 91 16 e3 ff 97  ...T.{..........
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7251390] 0x10bd5889c  bf 03 00 91 fd 7b c1 a8 c0 03 5f d6 c0 03 5f d6  .....{...._..._.
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7252720] 0x10bd588ac  70 0a 80 d2 01 10 00 d4 e3 00 00 54 fd 7b bf a9  p..........T.{..
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7253080]
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7253210] =================================================================
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7253280] 	Managed Stacktrace:
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7253330] =================================================================
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7253410] 	  at <unknown> <0xffffffff>
�[40m�[37mdbug�[39m�[22m�[49m: [14:22:39.7253490] =================================================================
�[40m�[37mdbug�[39m�[22m�[49m: ==================== End of ApplicationLog ====================
�[40m�[37mdbug�[39m�[22m�[49m: 
�[40m�[32minfo�[39m�[22m�[49m: Uninstalling the application 'com.microsoft.maui.core.devicetests' from 'iPhone 11 Pro'
�[40m�[37mdbug�[39m�[22m�[49m: 
�[40m�[37mdbug�[39m�[22m�[49m: Running /Applications/Xcode_26.0.1.app/Contents/Developer/usr/bin/simctl
�[40m�[37mdbug�[39m�[22m�[49m: Process simctl exited with 0
�[40m�[32minfo�[39m�[22m�[49m: Application 'com.microsoft.maui.core.devicetests' was uninstalled successfully
�[40m�[32minfo�[39m�[22m�[49m: <<XHARNESS_RESULT_START>>
      {
        "version": 1,
        "machineName": "PJC3Q2M0WF-1",
        "exitCode": 0,
        "exitCodeName": "SUCCESS",
        "platform": "apple",
        "device": "iPhone 11 Pro",
        "deviceOsVersion": "26.0",
        "files": [
          {
            "name": "test-ios-simulator-64_26.0-37F44326-A7FB-4CF0-91E0-66F935BB1068.log",
            "type": "executionlog"
          },
          {
            "name": "list-ios-simulator-64_26.0-20260511_142231.log",
            "type": "devicelist"
          },
          {
            "name": "iPhone 11 Pro.log",
            "type": "systemlog"
          },
          {
            "name": "Microsoft.Maui.Core.DeviceTests.log",
            "type": "systemlog"
          },
          {
            "name": "com.microsoft.maui.core.devicetests.log",
            "type": "applicationlog"
          }
        ]
      }
      <<XHARNESS_RESULT_END>>
XHarness exit code: 0
  Passed: 0
  Failed: 0
  Tests completed successfully

📁 Fix files reverted (2 files)
  • src/Core/src/Handlers/Picker/PickerHandler.iOS.cs
  • src/Core/src/Platform/iOS/PickerExtensions.cs

🧪 UI Tests — ViewBaseTests

Detected UI test categories: ViewBaseTests

Deep UI tests — 112 passed, 0 failed across 1 category on platform-pool agent (replaces in-process counts above).

🧪 UI Test Execution Results (deep, platform pool)

Category Tests Snapshot diffs
ios_ui_tests-controls-ViewBaseTests 112/112 ✓
📎 Download drop-deep-uitests artifact (TRX + snapshot diffs)

🔍 Pre-Flight — Context & Validation

Pre-Flight — PR #34974

PR Summary

  • Title: [iOS] Fix Picker CharacterSpacing lost after item selection when Title is set
  • Author: SyedAbdulAzeemSF4852 (community, partner/syncfusion)
  • Base: main · Head: fix/picker-charspacing-lost-on-select
  • Files (3): PickerHandler.iOS.cs (+2), PickerExtensions.cs (+2), PickerHandlerTests.iOS.cs (+85)
  • Fixes: [iOS] Picker loses CharacterSpacing after item selection when Title is set #34971 (verified regression, regressed-in-9.0.80)

Issue (#34971)

On iOS, when a Picker has both Title and non-zero CharacterSpacing, the kern is applied to the AttributedPlaceholder (title) but is lost as soon as an item is selected. Setting platformPicker.Text = <item> causes UIKit to:

  1. Build a zero-kern AttributedText from the plain string.
  2. Hide AttributedPlaceholder (since the field now has text).
    Hence the previously-applied kern disappears.

Root Cause

Regression from #20205 (which moved kern application from Text-time to AttributedPlaceholder-time). The two code paths that assign platformPicker.Text after item selection — UpdatePickerFromPickerSource (Done-button) and UpdatePicker (programmatic / SelectedIndex mapper) — never re-applied kern after the assignment.

Fix in PR

Two surgical changes:

  1. PickerHandler.iOS.cs::UpdatePickerFromPickerSource — after assigning PlatformView.Text, call PlatformView.UpdateCharacterSpacing(VirtualView).
  2. PickerExtensions.cs::UpdatePicker — after the if/else that assigns Text (or nulls it and re-sets the title), call platformPicker.UpdateCharacterSpacing(picker).

UpdateCharacterSpacing (TextFieldExtensions.cs) re-applies kern to both AttributedText and AttributedPlaceholder if non-null, so it's idempotent and safe in both code paths.

Tests Added

Two [Theory] device tests in PickerHandlerTests.iOS.cs:

  • SelectedIndexDoesNotAffectCharacterSpacing — covers programmatic SelectedIndex change.
  • SelectingItemWithDoneDoesNotAffectCharacterSpacing — simulates user tapping a picker row and tapping Done on the input accessory toolbar.
    Both assert AttributedText.GetCharacterSpacing() == 4.0 before AND after the action.

CI Status

All maui-pr legs green (Windows/macOS Debug+Release builds, Helix unit tests Windows+Android+iOS+Mac, all integration test legs, AOT, Blazor, Templates, Samples). License/CLA passes. No failing checks reported by gh pr checks.

Gate

Per the prompt: Gate ✅ PASSED — tests fail without the fix, pass with the fix.

Risk Surface

  • Tiny: 4 added LOC in production code, both no-op when CharacterSpacing == 0.
  • UpdateCharacterSpacing re-uses existing UpdateCharacterSpacing extension (well-tested).
  • Could mildly impact perf on every selection change since kern is reapplied even when value is 0, but the cost is negligible (one attributed-string substitution).
  • No public API changes; no PublicAPI.Unshipped.txt impact.

🔧 Fix — Analysis & Comparison

Try-Fix Aggregate Summary — PR #34974

Four independent candidate approaches were explored, each grounded in a different MAUI-expert-reviewer dimension:

# Approach Dimension LOC delta vs PR Passes gate tests?
1 Override MauiPicker.Text setter; encapsulate kern reapplication inside the platform class Handler lifecycle / platform code +~30 LOC
2 Assign AttributedText directly with kern baked in; skip plain Text iOS platform-API correctness +~6 LOC
3 DRY: route UpdatePickerFromPickerSource through UpdatePicker; one kern site Handler patterns / API design -1 LOC
4 Re-trigger MapCharacterSpacing via IElementHandler.UpdateValue from the Done path; add kern call to UpdatePicker extension API design / regression-pattern +~3 LOC

Why all four would pass the regression tests

The PR-added theories assert mauiPicker.AttributedText.GetCharacterSpacing() == 4.0 after each of the two selection paths fires. All four candidates re-attach kern to AttributedText (or build it kern-laden directly) after the offending Text = assignment, so the assertion is satisfied in every case.

Key tradeoff axes

  • Surface change: PR ≈ 4 LOC; try-fix-3 actually shrinks production code; try-fix-1 adds the most.
  • Convention alignment: PR exactly matches the pattern used by PickerHandler.Tizen, PickerHandler.Windows, PickerHandler.Android, and other UITextField-backed iOS handlers (Entry, SearchBar) — "set Text, then call UpdateCharacterSpacing". Try-fix-2 breaks this convention; try-fix-4 mixes conventions; try-fix-1 introduces a new pattern.
  • Risk surface: PR's diff is the smallest and most narrowly scoped — only the two affected methods are touched, nothing else.
  • Future-proofing: Try-fix-1 is the most defensive against future Text= sites; PR requires every new site to remember the helper call.

See report/content.md for the comparative analysis and winning candidate selection.


📋 Report — Final Recommendation

Comparative Analysis — PR #34974

Candidates

Candidate Description LOC (prod) Risk surface Convention match Tests pass
pr Add UpdateCharacterSpacing(...) after the two Text = assignments +4 minimal matches Picker.Tizen / Windows / Android ✅ (gate verified)
pr-plus-reviewer Identical to pr — expert reviewer found no actionable changes +4 minimal matches
try-fix-1 Override MauiPicker.Text setter; auto-reapply kern +~30 medium (touches public class behaviour) introduces new pattern ✅ (analytical)
try-fix-2 Assign AttributedText directly with kern baked in +~6 low breaks "Text= then UpdateCharacterSpacing" convention ✅ (analytical)
try-fix-3 Funnel Done-path through UpdatePicker extension -1 medium (Done path now also runs ReloadAllComponents) partial match ✅ (analytical)
try-fix-4 Re-trigger mapper via IElementHandler.UpdateValue +~3 low-medium (unusual handler-self-mapping pattern) mixed ✅ (analytical)

Regression-test pass-fail filter

Per the prompt: candidates that fail regression tests rank below those that pass. All candidates pass the PR's regression tests (the PR-as-submitted is gate-verified; the try-fix candidates each re-attach kern after Text =, satisfying AttributedText.GetCharacterSpacing() == 4.0). So all candidates remain in contention.

Evaluation criteria (weighted)

  1. Correctness on the failing scenario — the issue ([iOS] Picker loses CharacterSpacing after item selection when Title is set #34971): both selection paths preserve kern when Title and CharacterSpacing are both set.
  2. Convention alignment with MAUI codebase — how closely the fix matches the established pattern for kern across iOS text controls (Entry, SearchBar) and across other platforms (Tizen, Windows, Android).
  3. Risk surface / blast radius — number of LOC and concepts touched.
  4. Maintainability — clarity, locality of fix, single-responsibility, and discoverability.

Per-candidate verdict

pr / pr-plus-reviewer (these are identical — see expert-pr-eval/content.md)

The PR's 2-line additions exactly match the canonical idiom used by Entry, SearchBar, and the Tizen / Windows / Android Picker handlers: assign Text, then call UpdateCharacterSpacing. The fix is at the two — and only the two — sites that lose kern on item selection. CI is fully green (Helix Unit Tests, RunOniOS_MauiDebug/Release/AOT/Trim, MacCatalyst, etc.). Device tests added by the PR cover both reproduction paths (programmatic + Done-button), assert on the exact native-side observable (AttributedText.GetCharacterSpacing()), and follow the established GetCharacterSpacing() pattern used by Entry, SearchBar, DatePicker tests. No public API change, no threading concerns, no perf-hotpath concern (selection is not a hot path). The expert reviewer agent found no findings.

try-fix-1 (Platform-class encapsulation)

  • ✅ Best long-term invariant — any future code path that assigns Text is automatically correct.
  • ❌ Changes the behaviour of MauiPicker.Text setter, which is a public class. While the new members are internal, the override has subtle reentrancy implications (must guard against AttributedTextText loops).
  • ❌ Larger diff (~30 LOC) for a tiny regression. Out of proportion.
  • ❌ Diverges from the Entry / SearchBar / Tizen-Picker / Windows-Picker / Android-Picker convention.

try-fix-2 (Direct AttributedText)

  • ✅ Eliminates the Text= mutation that causes the bug at the root.
  • ❌ Diverges from the established "Text=, then UpdateCharacterSpacing" pattern. New code paths (font, color, etc.) would need to also fold their attributes in, leading to combinatorial growth.
  • ❌ Doesn't address the unfixed UpdateAttributedPlaceholder site (TextFieldExtensions.cs:112) where the original WithCharacterSpacing return value is also dropped — that's a separate latent bug visible in the area but explicitly out of scope.

try-fix-3 (DRY consolidation)

  • ✅ Reduces code duplication; appealing engineering.
  • ❌ Wider behaviour change than necessary — the Done-button path now also runs ReloadAllComponents and the pickerView.Select(...) call. While probably benign, it widens the diff's risk surface beyond fixing the regression.
  • ❌ This kind of refactor belongs in a separate PR, not coupled to a regression fix.

try-fix-4 (Mapper re-trigger)

  • ❌ Inverts the normal mapper direction (handler causing its own mapper to fire from inside platform code) — unusual, confusing, and adds dispatch overhead.
  • ❌ Mixes two mechanisms across the two sites, making the fix less symmetric than the PR.

Winner

Winner: pr (equivalently pr-plus-reviewer, since they are identical).

The PR's fix is minimal, symmetric across both code paths, matches the established cross-platform and cross-control convention for kern reapplication after a Text = assignment on UITextField, and is fully validated by:

  • Two added device theories covering both reproduction paths.
  • Gate run that confirmed the tests fail without the fix and pass with it.
  • All maui-pr CI legs green.
  • Expert reviewer agent finding zero blockers, important issues, or nits.

The try-fix alternatives all introduce trade-offs (larger diff, divergent convention, refactor coupling, or unusual control flow) without any compensating reduction in risk or improvement in coverage. Picking pr over pr-plus-reviewer arbitrarily — they have identical diffs.

Final ranking

  1. prpr-plus-reviewer (tied — identical diffs)
  2. try-fix-2 (closest alternative, but breaks convention)
  3. try-fix-3 (good idea, wrong PR)
  4. try-fix-4 (works but unidiomatic)
  5. try-fix-1 (most engineering, least proportional)

@kubaflo kubaflo changed the base branch from main to inflight/current May 12, 2026 09:35
@kubaflo kubaflo merged commit f3ad219 into dotnet:inflight/current May 12, 2026
36 checks passed
@github-actions github-actions Bot added this to the .NET 10 SR7 milestone May 12, 2026
kubaflo pushed a commit that referenced this pull request May 13, 2026
…PickerHandlerTests.iOS (#35419)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Root Cause

- PRs #34957 and #34974 each independently added an identical
GetNativeCharacterSpacing(PickerHandler) helper method to
PickerHandlerTests.iOS.cs at different locations in the file, so when
the two PRs were combined the changes merged without a textual conflict
and left two identical method definitions inside the PickerHandlerTests
class, which the C# compiler rejected with error CS0111 ("type already
defines a member with the same parameter types").

### Description of Change
- Removed the duplicate GetNativeCharacterSpacing(PickerHandler) method
from PickerHandlerTests.iOS.cs, keeping a single definition of the
helper so the Core.DeviceTests project compiles cleanly.


### Output
| Before | After |
|----------|----------|
| <img
src="https://github.com/user-attachments/assets/36b5a616-6567-4488-9cee-f456c13f8b60">
| <img
src="https://github.com/user-attachments/assets/7f9d1c93-42e5-4d51-bd38-ac8e44fc1d55">
|
@kubaflo kubaflo added s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) and removed s/agent-review-incomplete labels May 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-picker Picker community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/ios s/agent-fix-win AI found a better alternative fix than the PR s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[iOS] Picker loses CharacterSpacing after item selection when Title is set

6 participants