[iOS/Mac] Fix Entry clear button retaining tint color after TextColor is reset to null#35177
[iOS/Mac] Fix Entry clear button retaining tint color after TextColor is reset to null#35177SyedAbdulAzeemSF4852 wants to merge 5 commits intodotnet:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes an iOS/MacCatalyst Entry behavior where the clear button retains the previously tinted image after TextColor is reset to null, by ensuring UIKit can restore its default system-provided clear icon.
Changes:
- Clear the clear-button’s explicitly set images when
TextColorbecomesnullso the system image can be restored (iOS/MacCatalyst). - Make clear-button tint-image generation defensive against a
nullbase image. - Add an iOS device test asserting the clear button image returns to the original default after
TextColoris reset tonull.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/Core/src/Platform/iOS/TextFieldExtensions.cs | Resets the clear button’s images when TextColor is null and adds a null-guard in image tinting. |
| src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs | Adds a device test validating clear button image restoration when TextColor is cleared. |
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 5 findings
See inline comments for details.
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 8 findings
See inline comments for details.
MauiBot
left a comment
There was a problem hiding this comment.
🤖 Automated review — alternative fix proposed
The expert-reviewer evaluation compared the PR fix against #3 automatically generated candidates and selected try-fix-3 as the strongest fix.
Why: Try-fix-3 (gpt-5.3-codex) passes 2516/2516 device tests, changes only TextFieldExtensions.cs (single file), and fixes both the null-reset bug AND the pre-existing color-to-color drift by calling SetImage(null) before both the null and color paths. The PR fix (Gate failed) and pr-plus-reviewer only address the null-reset path. Try-fix-3 is the simplest, most complete, and best-validated candidate.
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-3`)
diff --git a/src/Core/src/Platform/iOS/TextFieldExtensions.cs b/src/Core/src/Platform/iOS/TextFieldExtensions.cs
index 107160fb73..4b9f10952e 100644
--- a/src/Core/src/Platform/iOS/TextFieldExtensions.cs
+++ b/src/Core/src/Platform/iOS/TextFieldExtensions.cs
@@ -227,20 +227,33 @@ namespace Microsoft.Maui.Platform
{
if (textField.ValueForKey(new NSString("clearButton")) is UIButton clearButton)
{
- UIImage defaultClearImage = clearButton.ImageForState(UIControlState.Highlighted);
-
if (entry.TextColor is null)
{
// Setting TintColor to null allows the system to automatically apply the appropriate color based on the current theme (light or dark mode)
clearButton.TintColor = null;
+ clearButton.SetImage(null, UIControlState.Normal);
+ clearButton.SetImage(null, UIControlState.Highlighted);
}
else
{
- clearButton.TintColor = entry.TextColor.ToPlatform();
+ // Clear any previously assigned custom image before fetching the source image to prevent tint drift across color→color transitions.
+ clearButton.SetImage(null, UIControlState.Normal);
+ clearButton.SetImage(null, UIControlState.Highlighted);
+
+ UIImage? defaultClearImage = clearButton.ImageForState(UIControlState.Highlighted) ??
+ clearButton.ImageForState(UIControlState.Normal);
+ if (defaultClearImage is null)
+ return;
+
+ var tintColor = entry.TextColor.ToPlatform();
+ clearButton.TintColor = tintColor;
- var tintedClearImage = GetClearButtonTintImage(defaultClearImage, entry.TextColor.ToPlatform());
- clearButton.SetImage(tintedClearImage, UIControlState.Normal);
- clearButton.SetImage(tintedClearImage, UIControlState.Highlighted);
+ var tintedClearImage = GetClearButtonTintImage(defaultClearImage, tintColor);
+ if (tintedClearImage is not null)
+ {
+ clearButton.SetImage(tintedClearImage, UIControlState.Normal);
+ clearButton.SetImage(tintedClearImage, UIControlState.Highlighted);
+ }
}
}
}
kubaflo
left a comment
There was a problem hiding this comment.
Could you please try the AI's suggestions?
MauiBot
left a comment
There was a problem hiding this comment.
🤖 Automated review — alternative fix proposed
The expert-reviewer evaluation compared the PR fix against #2 automatically generated candidates and selected try-fix-2 as the strongest fix.
Why: try-fix-2 uses UIKit's native AlwaysTemplate+TintColor mechanism instead of a pixel renderer, eliminating the color-to-color compound-tinting risk and the TintColor/image state mismatch found by code review. It removes GetClearButtonTintImage entirely (simpler), and replaces fragile RenderingMode assertions with observable TintColor checks. The PR's fix fails its own gate test (XHarness APP_LAUNCH_FAILURE); try-fix-2 passed its test run.
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-2`)
diff --git a/src/Core/src/Platform/iOS/TextFieldExtensions.cs b/src/Core/src/Platform/iOS/TextFieldExtensions.cs
index 7d1040697b..eded811095 100644
--- a/src/Core/src/Platform/iOS/TextFieldExtensions.cs
+++ b/src/Core/src/Platform/iOS/TextFieldExtensions.cs
@@ -1,5 +1,4 @@
using System;
-using CoreGraphics;
using Foundation;
using Microsoft.Maui.Graphics;
using ObjCRuntime;
@@ -229,61 +228,38 @@ namespace Microsoft.Maui.Platform
{
if (entry.TextColor is null)
{
- // Setting TintColor to null allows the system to automatically apply the appropriate color based on the current theme (light or dark mode)
- clearButton.TintColor = null;
- // SetImage(null) releases the custom tinted bitmap so UIKit restores its system default.
- // The color path (else branch) reads ImageForState(.Highlighted) to get that original
- // image as the source for tinting. Without these calls, TintColor=null has no visual effect.
+ // Clear images first so UIKit's default system image is restored before TintColor
+ // inheritance takes effect. Without this, the custom tinted bitmap stays pinned.
clearButton.SetImage(null, UIControlState.Normal);
clearButton.SetImage(null, UIControlState.Highlighted);
+ // Setting TintColor to null allows the system to automatically apply the appropriate color based on the current theme (light or dark mode)
+ clearButton.TintColor = null;
}
else
{
- // On a null→color transition, UIKit restores the system image after SetImage(null),
- // so ImageForState(Highlighted) returns the system clear button image as the tinting source.
- UIImage? defaultClearImage = clearButton.ImageForState(UIControlState.Highlighted);
+ // The Highlighted state always returns the system image when no custom image is set,
+ // including after SetImage(null, Highlighted) which causes UIKit to restore its default.
+ // Converting to AlwaysTemplate lets UIKit apply TintColor at render time without
+ // requiring manual pixel blending via UIGraphicsImageRenderer.
+ var sourceImage = clearButton.ImageForState(UIControlState.Highlighted);
+
+ // Always apply TintColor so the color takes effect even if sourceImage is null.
clearButton.TintColor = entry.TextColor.ToPlatform();
- var tintedClearImage = GetClearButtonTintImage(defaultClearImage, entry.TextColor.ToPlatform());
- if (tintedClearImage is not null)
+ if (sourceImage is not null)
{
- clearButton.SetImage(tintedClearImage, UIControlState.Normal);
- clearButton.SetImage(tintedClearImage, UIControlState.Highlighted);
+ // Avoid creating a redundant wrapper when the image is already in template mode
+ // (e.g., on a color→color transition the previously-set template image is returned).
+ var templateImage = sourceImage.RenderingMode == UIImageRenderingMode.AlwaysTemplate
+ ? sourceImage
+ : sourceImage.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate);
+ clearButton.SetImage(templateImage, UIControlState.Normal);
+ clearButton.SetImage(templateImage, UIControlState.Highlighted);
}
}
}
}
- internal static UIImage? GetClearButtonTintImage(UIImage? image, UIColor color)
- {
- if (image is null)
- {
- return null;
- }
-
- var size = image.Size;
-
- var renderer = new UIGraphicsImageRenderer(size, new UIGraphicsImageRendererFormat()
- {
- Opaque = false,
- Scale = UIScreen.MainScreen.Scale,
- });
-
- if (renderer is null)
- {
- return null;
- }
-
- return renderer.CreateImage((context) =>
- {
- image.Draw(CGPoint.Empty, CGBlendMode.Normal, 1.0f);
- color.ColorWithAlpha(1.0f).SetFill();
-
- var rect = new CGRect(CGPoint.Empty.X, CGPoint.Empty.Y, image.Size.Width, image.Size.Height);
- context?.FillRect(rect, CGBlendMode.SourceIn);
- });
- }
-
internal static void AddMauiDoneAccessoryView(this UITextField textField, IViewHandler handler)
{
#if !MACCATALYST
diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs
index 1cb5c3f889..954f37abc2 100644
--- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs
+++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs
@@ -112,34 +112,32 @@ namespace Microsoft.Maui.DeviceTests
var clearButton = GetNativeClearButton(handler);
Assert.NotNull(clearButton);
- var defaultImage = clearButton.ImageForState(UIControlState.Normal);
- Assert.NotNull(defaultImage);
- Assert.Equal(UIImageRenderingMode.AlwaysOriginal, defaultImage.RenderingMode);
-
+ // Set a custom text color — clear button should receive a template image with custom tint
entry.TextColor = Colors.Purple;
handler.UpdateValue(nameof(IEntry.TextColor));
var tintedImage = clearButton.ImageForState(UIControlState.Normal);
Assert.NotNull(tintedImage);
- Assert.Equal(UIImageRenderingMode.Automatic, tintedImage.RenderingMode);
+ var purpleTintColor = clearButton.TintColor;
+ Assert.NotNull(purpleTintColor);
+ // Reset text color to null — clear button must release the custom template image
+ // and restore the inherited system tint (no longer purple).
entry.TextColor = null;
handler.UpdateValue(nameof(IEntry.TextColor));
- // UIKit restores the original AlwaysOriginal system image when SetImage(null) is called
- // on this private clearButton — ImageForState(.Highlighted) must return non-null for re-tinting to work.
- var resetImage = clearButton.ImageForState(UIControlState.Normal);
- Assert.NotNull(resetImage);
- Assert.Equal(UIImageRenderingMode.AlwaysOriginal, resetImage.RenderingMode);
+ // Bug assertion: without the fix, TintColor would still equal purpleTintColor here.
+ // With the fix, TintColor is either null (unset) or the inherited system default — either
+ // way it must not be the purple we explicitly applied.
+ Assert.NotEqual(purpleTintColor, clearButton.TintColor);
+ // Re-tint with a different color — verify tinting still works after a null reset
entry.TextColor = Colors.Blue;
handler.UpdateValue(nameof(IEntry.TextColor));
- // Verify re-tinting works after reset (null→color→null→color)
- // Confirms ImageForState(.Highlighted) returns the original after SetImage(null)
var retintedImage = clearButton.ImageForState(UIControlState.Normal);
Assert.NotNull(retintedImage);
- Assert.Equal(UIImageRenderingMode.Automatic, retintedImage.RenderingMode);
+ Assert.NotEqual(purpleTintColor, clearButton.TintColor);
});
}
MauiBot
left a comment
There was a problem hiding this comment.
🤖 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 (Reset-First) passes device tests, fixes the reported bug AND the pre-existing color→color compound-tinting issue by calling SetImage(null) at the top of both branches before any image read, ensuring ImageForState always returns a clean system image. It is simpler than try-fix-2 (no static WeakTable state) and more direct than try-fix-4 (no temp UITextField). The code review's hard gate (NEEDS_CHANGES) and Gate failure rule out the original PR. Note: an even better approach emerged from cross-pollination (AlwaysTemplate rendering mode, attempt-5) which eliminates GetClearButtonTintImage entirely; the author should strongly consider adopting that instead.
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/Platform/iOS/TextFieldExtensions.cs b/src/Core/src/Platform/iOS/TextFieldExtensions.cs
index 107160fb73..6634a1451e 100644
--- a/src/Core/src/Platform/iOS/TextFieldExtensions.cs
+++ b/src/Core/src/Platform/iOS/TextFieldExtensions.cs
@@ -227,26 +227,42 @@ namespace Microsoft.Maui.Platform
{
if (textField.ValueForKey(new NSString("clearButton")) is UIButton clearButton)
{
- UIImage defaultClearImage = clearButton.ImageForState(UIControlState.Highlighted);
-
if (entry.TextColor is null)
{
- // Setting TintColor to null allows the system to automatically apply the appropriate color based on the current theme (light or dark mode)
clearButton.TintColor = null;
+ // Release any custom tinted bitmap so UIKit restores its system default.
+ clearButton.SetImage(null, UIControlState.Normal);
+ clearButton.SetImage(null, UIControlState.Highlighted);
}
else
{
- clearButton.TintColor = entry.TextColor.ToPlatform();
-
- var tintedClearImage = GetClearButtonTintImage(defaultClearImage, entry.TextColor.ToPlatform());
- clearButton.SetImage(tintedClearImage, UIControlState.Normal);
- clearButton.SetImage(tintedClearImage, UIControlState.Highlighted);
+ // Clear any previous custom image first so ImageForState(.Highlighted)
+ // reliably returns the original system image -- this prevents compound
+ // tinting during color->color transitions (not just null->color).
+ clearButton.SetImage(null, UIControlState.Normal);
+ clearButton.SetImage(null, UIControlState.Highlighted);
+
+ UIImage? defaultClearImage = clearButton.ImageForState(UIControlState.Highlighted);
+ var platformColor = entry.TextColor.ToPlatform();
+ clearButton.TintColor = platformColor;
+
+ var tintedClearImage = GetClearButtonTintImage(defaultClearImage, platformColor);
+ if (tintedClearImage is not null)
+ {
+ clearButton.SetImage(tintedClearImage, UIControlState.Normal);
+ clearButton.SetImage(tintedClearImage, UIControlState.Highlighted);
+ }
}
}
}
- internal static UIImage? GetClearButtonTintImage(UIImage image, UIColor color)
+ internal static UIImage? GetClearButtonTintImage(UIImage? image, UIColor color)
{
+ if (image is null)
+ {
+ return null;
+ }
+
var size = image.Size;
var renderer = new UIGraphicsImageRenderer(size, new UIGraphicsImageRendererFormat()|
/azd run maui-pr-devicetests |
MauiBot
left a comment
There was a problem hiding this comment.
🤖 Automated review — alternative fix proposed
The expert-reviewer evaluation compared the PR fix against #4 automatically generated candidates and selected try-fix-4 as the strongest fix.
Why: try-fix-4 (unconditional SetImage(null) before all branches) passed both the primary device test and the Issue32886 regression test, while the original PR fix failed the Gate. try-fix-4 also fixes the color-to-color compound tinting edge case that the PR leaves unresolved, making it a strictly superior fix with full null safety in GetClearButtonTintImage.
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-4`)
diff --git a/src/Core/src/Platform/iOS/TextFieldExtensions.cs b/src/Core/src/Platform/iOS/TextFieldExtensions.cs
index 107160fb73..d210fa5212 100644
--- a/src/Core/src/Platform/iOS/TextFieldExtensions.cs
+++ b/src/Core/src/Platform/iOS/TextFieldExtensions.cs
@@ -227,7 +227,11 @@ namespace Microsoft.Maui.Platform
{
if (textField.ValueForKey(new NSString("clearButton")) is UIButton clearButton)
{
-UIImage defaultClearImage = clearButton.ImageForState(UIControlState.Highlighted);
+// Always reset the pinned image first so UIKit restores the system default.
+// This prevents stale tinted bitmaps in both the null and color paths,
color transitions without compound tinting.
+clearButton.SetImage(null, UIControlState.Normal);
+clearButton.SetImage(null, UIControlState.Highlighted);
if (entry.TextColor is null)
{
@@ -236,17 +240,28 @@ namespace Microsoft.Maui.Platform
}
else
{
-clearButton.TintColor = entry.TextColor.ToPlatform();
-
-var tintedClearImage = GetClearButtonTintImage(defaultClearImage, entry.TextColor.ToPlatform());
-clearButton.SetImage(tintedClearImage, UIControlState.Normal);
-clearButton.SetImage(tintedClearImage, UIControlState.Highlighted);
+// After SetImage(null), UIKit has restored the system clear button image
+// read it now as the source for custom tinting.
+UIImage? defaultClearImage = clearButton.ImageForState(UIControlState.Highlighted);
+var platformColor = entry.TextColor.ToPlatform();
+clearButton.TintColor = platformColor;
+
+var tintedClearImage = GetClearButtonTintImage(defaultClearImage, platformColor);
+if (tintedClearImage is not null)
+{
+clearButton.SetImage(tintedClearImage, UIControlState.Normal);
+clearButton.SetImage(tintedClearImage, UIControlState.Highlighted);
+}
}
}
}
-internal static UIImage? GetClearButtonTintImage(UIImage image, UIColor color)
+internal static UIImage? GetClearButtonTintImage(UIImage? image, UIColor color)
{
+if (image is null)
+{
+return null;
+}
var size = image.Size;
var renderer = new UIGraphicsImageRenderer(size, new UIGraphicsImageRendererFormat()
diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs
index 753c158cb3..1cb5c3f889 100644
--- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs
+++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs
@@ -93,6 +93,56 @@ namespace Microsoft.Maui.DeviceTests
Assert.Equal(xplatCharacterSpacing, values.PlatformViewValue);
}
+[Fact(DisplayName = "Clear button image resets when TextColor is null")]
+public async Task ClearButtonImageResetsWhenTextColorIsNull()
+{
+EntryStub entry = new EntryStub
+{
+Text = "MAUI",
+ClearButtonVisibility = ClearButtonVisibility.WhileEditing,
+TextColor = null
+};
+
+await AttachAndRun(entry, async (handler) =>
+{
+await AssertEventually(() => handler.PlatformView.IsLoaded());
+Assert.True(handler.PlatformView.BecomeFirstResponder());
+await AssertEventually(() => handler.PlatformView.IsFirstResponder);
+
+var clearButton = GetNativeClearButton(handler);
+Assert.NotNull(clearButton);
+
+var defaultImage = clearButton.ImageForState(UIControlState.Normal);
+Assert.NotNull(defaultImage);
+Assert.Equal(UIImageRenderingMode.AlwaysOriginal, defaultImage.RenderingMode);
+
+entry.TextColor = Colors.Purple;
+handler.UpdateValue(nameof(IEntry.TextColor));
+
+var tintedImage = clearButton.ImageForState(UIControlState.Normal);
+Assert.NotNull(tintedImage);
+Assert.Equal(UIImageRenderingMode.Automatic, tintedImage.RenderingMode);
+
+entry.TextColor = null;
+handler.UpdateValue(nameof(IEntry.TextColor));
+
+var resetImage = clearButton.ImageForState(UIControlState.Normal);
+Assert.NotNull(resetImage);
+Assert.Equal(UIImageRenderingMode.AlwaysOriginal, resetImage.RenderingMode);
+
+entry.TextColor = Colors.Blue;
+handler.UpdateValue(nameof(IEntry.TextColor));
+
+var retintedImage = clearButton.ImageForState(UIControlState.Normal);
+Assert.NotNull(retintedImage);
+Assert.Equal(UIImageRenderingMode.Automatic, retintedImage.RenderingMode);
+});
+}
+
[Fact]
public async Task NextMovesToNextEntry()
{
@@ -832,6 +882,9 @@ namespace Microsoft.Maui.DeviceTests
bool GetNativeClearButtonVisibility(EntryHandler entryHandler) =>
GetNativeEntry(entryHandler).ClearButtonMode == UITextFieldViewMode.WhileEditing;
+static UIButton GetNativeClearButton(EntryHandler entryHandler) =>
+GetNativeEntry(entryHandler).ValueForKey(new NSString("clearButton")) as UIButton;
+
UITextAlignment GetNativeHorizontalTextAlignment(EntryHandler entryHandler) =>
GetNativeEntry(entryHandler).TextAlignment;
🤖 AI Summary
📊 Review Session —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
📱 EntryHandlerTests (ClearButtonImageResetsWhenTextColorIsNull) Category=Entry |
✅ FAIL — 454s | ❌ FAIL — 176s |
🔴 Without fix — 📱 EntryHandlerTests (ClearButtonImageResetsWhenTextColorIsNull): FAIL ✅ · 454s
(truncated to last 15,000 chars)
LoopRun + 1208
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x00000001869389e8 CoreFoundation`CFRunLoopRunSpecific + 572
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x0000000187f08c78 Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x0000000187f7c3a4 Foundation`-[NSRunLoop(NSRunLoop) runUntilDate:] + 100
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x0000000102e6af28 mlaunch`xamarin_dyn_objc_msgSend + 160
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x0000000106698f44
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x00000001068f4aa8
�[40m�[37mdbug�[39m�[22m�[49m: frame #12: 0x0000000106693f84
�[40m�[37mdbug�[39m�[22m�[49m: frame #13: 0x00000001065110b4
�[40m�[37mdbug�[39m�[22m�[49m: frame #14: 0x0000000105d2cd54
�[40m�[37mdbug�[39m�[22m�[49m: frame #15: 0x0000000104bc8c04 libcoreclr.dylib`CallDescrWorkerInternal + 132
�[40m�[37mdbug�[39m�[22m�[49m: frame #16: 0x0000000104a46d30 libcoreclr.dylib`MethodDescCallSite::CallTargetWorker(unsigned long long const*, unsigned long long*, int) + 836
�[40m�[37mdbug�[39m�[22m�[49m: frame #17: 0x000000010494d350 libcoreclr.dylib`RunMain(MethodDesc*, short, int*, PtrArray**) + 648
�[40m�[37mdbug�[39m�[22m�[49m: frame #18: 0x000000010494d688 libcoreclr.dylib`Assembly::ExecuteMainMethod(PtrArray**, int) + 264
�[40m�[37mdbug�[39m�[22m�[49m: frame #19: 0x000000010497529c libcoreclr.dylib`CorHost2::ExecuteAssembly(unsigned int, char16_t const*, int, char16_t const**, unsigned int*) + 640
�[40m�[37mdbug�[39m�[22m�[49m: frame #20: 0x000000010493b650 libcoreclr.dylib`coreclr_execute_assembly + 232
�[40m�[37mdbug�[39m�[22m�[49m: frame #21: 0x0000000102e66140 mlaunch`mono_jit_exec + 204
�[40m�[37mdbug�[39m�[22m�[49m: frame #22: 0x0000000102e69ecc mlaunch`xamarin_main + 884
�[40m�[37mdbug�[39m�[22m�[49m: frame #23: 0x0000000102e6b1f4 mlaunch`main + 64
�[40m�[37mdbug�[39m�[22m�[49m: frame #24: 0x00000001864aeb98 dyld`start + 6076
�[40m�[37mdbug�[39m�[22m�[49m: thread #2
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018680f8b0 libsystem_kernel.dylib`__workq_kernreturn + 8
�[40m�[37mdbug�[39m�[22m�[49m: thread #3
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018680dc34 libsystem_kernel.dylib`mach_msg2_trap + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x00000001868203a0 libsystem_kernel.dylib`mach_msg2_internal + 76
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x0000000186816764 libsystem_kernel.dylib`mach_msg_overwrite + 484
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000018680dfa8 libsystem_kernel.dylib`mach_msg + 24
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x00000001049392f4 libcoreclr.dylib`MachMessage::Receive(unsigned int) + 80
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x000000010493861c libcoreclr.dylib`SEHExceptionThread(void*) + 164
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x000000018684fbc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #4, name = '.NET SynchManager'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x0000000186813d04 libsystem_kernel.dylib`kevent + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000010492d304 libcoreclr.dylib`CorUnix::CPalSynchronizationManager::ReadBytesFromProcessPipe(int, unsigned char*, int) + 484
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010492c9f0 libcoreclr.dylib`CorUnix::CPalSynchronizationManager::WorkerThread(void*) + 164
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x00000001049360fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000018684fbc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #5, name = '.NET EventPipe'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x0000000186816498 libsystem_kernel.dylib`poll + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x0000000104c28e90 libcoreclr.dylib`ds_ipc_poll(_DiagnosticsIpcPollHandle*, unsigned long, unsigned int, void (*)(char const*, unsigned int)) + 172
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x0000000104cd6bb0 libcoreclr.dylib`ds_ipc_stream_factory_get_next_available_stream(void (*)(char const*, unsigned int)) + 756
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x0000000104cd4a68 libcoreclr.dylib`server_thread(void*) + 372
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x00000001049360fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x000000018684fbc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #6, name = '.NET DebugPipe'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018680e678 libsystem_kernel.dylib`__open + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x00000001868196a4 libsystem_kernel.dylib`open + 64
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x0000000104c29a84 libcoreclr.dylib`TwoWayPipe::WaitForConnection() + 40
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x0000000104c24578 libcoreclr.dylib`DbgTransportSession::TransportWorker() + 232
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x0000000104c235c8 libcoreclr.dylib`DbgTransportSession::TransportWorkerStatic(void*) + 40
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x00000001049360fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x000000018684fbc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #7, name = '.NET Debugger'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x00000001868113cc libsystem_kernel.dylib`__psynch_cvwait + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018685009c libsystem_pthread.dylib`_pthread_cond_wait + 984
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010492af6c libcoreclr.dylib`CorUnix::CPalSynchronizationManager::ThreadNativeWait(CorUnix::_ThreadNativeWaitData*, unsigned int, CorUnix::ThreadWakeupReason*, unsigned int*) + 320
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000010492abec libcoreclr.dylib`CorUnix::CPalSynchronizationManager::BlockThread(CorUnix::CPalThread*, unsigned int, bool, bool, CorUnix::ThreadWakeupReason*, unsigned int*) + 380
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000010492f0cc libcoreclr.dylib`CorUnix::InternalWaitForMultipleObjectsEx(CorUnix::CPalThread*, unsigned int, void* const*, int, unsigned int, int, int) + 1600
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x0000000104c21da8 libcoreclr.dylib`DebuggerRCThread::MainLoop() + 228
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x0000000104c21c70 libcoreclr.dylib`DebuggerRCThread::ThreadProc() + 256
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x0000000104c21a24 libcoreclr.dylib`DebuggerRCThread::ThreadProcStatic(void*) + 56
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x00000001049360fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x000000018684fbc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #8
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x00000001868113cc libsystem_kernel.dylib`__psynch_cvwait + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x000000018685009c libsystem_pthread.dylib`_pthread_cond_wait + 984
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010492af6c libcoreclr.dylib`CorUnix::CPalSynchronizationManager::ThreadNativeWait(CorUnix::_ThreadNativeWaitData*, unsigned int, CorUnix::ThreadWakeupReason*, unsigned int*) + 320
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000010492abec libcoreclr.dylib`CorUnix::CPalSynchronizationManager::BlockThread(CorUnix::CPalThread*, unsigned int, bool, bool, CorUnix::ThreadWakeupReason*, unsigned int*) + 380
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000010492f0cc libcoreclr.dylib`CorUnix::InternalWaitForMultipleObjectsEx(CorUnix::CPalThread*, unsigned int, void* const*, int, unsigned int, int, int) + 1600
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x0000000104a7c078 libcoreclr.dylib`FinalizerThread::WaitForFinalizerEvent(CLREvent*) + 240
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x0000000104a7c1d8 libcoreclr.dylib`FinalizerThread::FinalizerThreadWorker(void*) + 264
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x0000000104a19fa8 libcoreclr.dylib`ManagedThreadBase_DispatchOuter(ManagedThreadCallState*) + 248
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x0000000104a1a48c libcoreclr.dylib`ManagedThreadBase::FinalizerBase(void (*)(void*)) + 36
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x0000000104a7c350 libcoreclr.dylib`FinalizerThread::FinalizerThreadStart(void*) + 88
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x00000001049360fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x000000018684fbc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #9, name = '.NET SigHandler'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018680e7dc libsystem_kernel.dylib`read + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x0000000102ff8e98 libSystem.Native.dylib`SignalHandlerLoop + 96
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000018684fbc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #10
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x0000000186813d04 libsystem_kernel.dylib`kevent + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x0000000102ff74a4 libSystem.Native.dylib`SystemNative_WaitForSocketEvents + 80
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000010669c11c
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000010669be5c
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000010669bd84
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x0000000106571350
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x00000001065711e0
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x0000000106571108
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x0000000104bc8c04 libcoreclr.dylib`CallDescrWorkerInternal + 132
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x0000000104a46988 libcoreclr.dylib`DispatchCallSimple(unsigned long*, unsigned int, unsigned long long, unsigned int) + 268
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x0000000104a58c6c libcoreclr.dylib`ThreadNative::KickOffThread_Worker(void*) + 148
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x0000000104a19fa8 libcoreclr.dylib`ManagedThreadBase_DispatchOuter(ManagedThreadCallState*) + 248
�[40m�[37mdbug�[39m�[22m�[49m: frame #12: 0x0000000104a1a45c libcoreclr.dylib`ManagedThreadBase::KickOff(void (*)(void*), void*) + 32
�[40m�[37mdbug�[39m�[22m�[49m: frame #13: 0x0000000104a58d44 libcoreclr.dylib`ThreadNative::KickOffThread(void*) + 172
�[40m�[37mdbug�[39m�[22m�[49m: frame #14: 0x00000001049360fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #15: 0x000000018684fbc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #11
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018680dc34 libsystem_kernel.dylib`mach_msg2_trap + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x00000001868203a0 libsystem_kernel.dylib`mach_msg2_internal + 76
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x0000000186816764 libsystem_kernel.dylib`mach_msg_overwrite + 484
�[40m�[37mdbug�[39m�[22m�[49m: frame #3: 0x000000018680dfa8 libsystem_kernel.dylib`mach_msg + 24
�[40m�[37mdbug�[39m�[22m�[49m: frame #4: 0x000000018693ac0c CoreFoundation`__CFRunLoopServiceMachPort + 160
�[40m�[37mdbug�[39m�[22m�[49m: frame #5: 0x0000000186939528 CoreFoundation`__CFRunLoopRun + 1208
�[40m�[37mdbug�[39m�[22m�[49m: frame #6: 0x00000001869389e8 CoreFoundation`CFRunLoopRunSpecific + 572
�[40m�[37mdbug�[39m�[22m�[49m: frame #7: 0x0000000187f08c78 Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
�[40m�[37mdbug�[39m�[22m�[49m: frame #8: 0x0000000102e6af28 mlaunch`xamarin_dyn_objc_msgSend + 160
�[40m�[37mdbug�[39m�[22m�[49m: frame #9: 0x00000001068ead24
�[40m�[37mdbug�[39m�[22m�[49m: frame #10: 0x00000001068eabe8
�[40m�[37mdbug�[39m�[22m�[49m: frame #11: 0x00000001068eaa1c
�[40m�[37mdbug�[39m�[22m�[49m: frame #12: 0x00000001068e7598
�[40m�[37mdbug�[39m�[22m�[49m: frame #13: 0x00000001065712f8
�[40m�[37mdbug�[39m�[22m�[49m: frame #14: 0x00000001065711e0
�[40m�[37mdbug�[39m�[22m�[49m: frame #15: 0x0000000106571108
�[40m�[37mdbug�[39m�[22m�[49m: frame #16: 0x0000000104bc8c04 libcoreclr.dylib`CallDescrWorkerInternal + 132
�[40m�[37mdbug�[39m�[22m�[49m: frame #17: 0x0000000104a46988 libcoreclr.dylib`DispatchCallSimple(unsigned long*, unsigned int, unsigned long long, unsigned int) + 268
�[40m�[37mdbug�[39m�[22m�[49m: frame #18: 0x0000000104a58c6c libcoreclr.dylib`ThreadNative::KickOffThread_Worker(void*) + 148
�[40m�[37mdbug�[39m�[22m�[49m: frame #19: 0x0000000104a19fa8 libcoreclr.dylib`ManagedThreadBase_DispatchOuter(ManagedThreadCallState*) + 248
�[40m�[37mdbug�[39m�[22m�[49m: frame #20: 0x0000000104a1a45c libcoreclr.dylib`ManagedThreadBase::KickOff(void (*)(void*), void*) + 32
�[40m�[37mdbug�[39m�[22m�[49m: frame #21: 0x0000000104a58d44 libcoreclr.dylib`ThreadNative::KickOffThread(void*) + 172
�[40m�[37mdbug�[39m�[22m�[49m: frame #22: 0x00000001049360fc libcoreclr.dylib`CorUnix::CPalThread::ThreadEntry(void*) + 364
�[40m�[37mdbug�[39m�[22m�[49m: frame #23: 0x000000018684fbc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #12, name = 'com.apple.CFSocket.private'
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x0000000186818c2c libsystem_kernel.dylib`__select + 8
�[40m�[37mdbug�[39m�[22m�[49m: frame #1: 0x0000000186960a80 CoreFoundation`__CFSocketManager + 704
�[40m�[37mdbug�[39m�[22m�[49m: frame #2: 0x000000018684fbc8 libsystem_pthread.dylib`_pthread_start + 136
�[40m�[37mdbug�[39m�[22m�[49m: thread #13
�[40m�[37mdbug�[39m�[22m�[49m: frame #0: 0x000000018680f8b0 libsystem_kernel.dylib`__workq_kernreturn + 8
�[40m�[37mdbug�[39m�[22m�[49m: (lldb) detach
�[40m�[37mdbug�[39m�[22m�[49m: Process 9365 detached
�[40m�[37mdbug�[39m�[22m�[49m: (lldb) quit
�[40m�[37mdbug�[39m�[22m�[49m: 9365 Execution timed out after 60 seconds and the process was killed.
�[40m�[37mdbug�[39m�[22m�[49m: Process mlaunch exited with 137
�[40m�[37mdbug�[39m�[22m�[49m: Failed to list crash reports from device.
�[40m�[37mdbug�[39m�[22m�[49m: Test run started but crashed and no test results were reported
�[40m�[37mdbug�[39m�[22m�[49m: No crash reports, waiting 30 seconds for the crash report service...
�[41m�[30mfail�[39m�[22m�[49m: Application test run crashed
Failed to launch the application, please try again. If the problem persists, try rebooting MacOS
�[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.1.1.app/Contents/Developer/usr/bin/simctl
�[40m�[37mdbug�[39m�[22m�[49m: An error was encountered processing the command (domain=com.apple.CoreSimulator.SimError, code=405):
�[40m�[37mdbug�[39m�[22m�[49m: Unable to lookup in current state: Shutdown
�[40m�[37mdbug�[39m�[22m�[49m: Process simctl exited with 149
�[41m�[30mfail�[39m�[22m�[49m: Failed to uninstall the app bundle! Check logs for more details!
XHarness exit code: 83 (APP_LAUNCH_FAILURE)
Passed: 0
Failed: 0
Tests completed with exit code: 83
🟢 With fix — 📱 EntryHandlerTests (ClearButtonImageResetsWhenTextColorIsNull): FAIL ❌ · 176s
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14038068
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Release/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14038068
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Release/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14038068
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Release/net10.0-ios26.0/Microsoft.Maui.dll
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Release/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14038068
TestUtils.DeviceTests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/TestUtils.DeviceTests/Release/net10.0-ios/Microsoft.Maui.TestUtils.DeviceTests.dll
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Release/net10.0-ios26.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14038068
Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Release/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
TestUtils.DeviceTests.Runners -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/TestUtils.DeviceTests.Runners/Release/net10.0-ios/Microsoft.Maui.TestUtils.DeviceTests.Runners.dll
Core.DeviceTests.Shared -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core.DeviceTests.Shared/Release/net10.0-ios/Microsoft.Maui.DeviceTests.Shared.dll
TestUtils.DeviceTests.Runners.SourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/TestUtils.DeviceTests.Runners.SourceGen/Release/netstandard2.0/Microsoft.Maui.TestUtils.DeviceTests.Runners.SourceGen.dll
Detected signing identity:
Code Signing Key: "" (-)
Provisioning Profile: "" () - no entitlements
Bundle Id: com.microsoft.maui.core.devicetests
App Id: com.microsoft.maui.core.devicetests
Core.DeviceTests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core.DeviceTests/Release/net10.0-ios/iossimulator-arm64/Microsoft.Maui.Core.DeviceTests.dll
Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
Optimizing assemblies for size. This process might take a while.
IL stripping assemblies
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:02:21.44
[11.0.0-prerelease.26107.1+bfbac237157e59cdbd19334325b2af80bd6e9828] XHarness command issued: apple test --app artifacts/bin/Core.DeviceTests/Release/net10.0-ios/iossimulator-arm64/Microsoft.Maui.Core.DeviceTests.app --target ios-simulator-64_18.6 --device C88D103F-1987-47D2-841B-8D6FEAA5E2A5 -o artifacts/log --timeout 01:00:00 -v --set-env=TestFilter=Category=Entry
�[40m�[32minfo�[39m�[22m�[49m: Preparing run for ios-simulator-64_18.6 targeting C88D103F-1987-47D2-841B-8D6FEAA5E2A5
�[40m�[32minfo�[39m�[22m�[49m: Looking for available ios-simulator-64_18.6 simulators..
�[40m�[37mdbug�[39m�[22m�[49m: Looking for available ios-simulator-64_18.6 simulators. Storing logs into list-ios-simulator-64_18.6-20260507_044506.log
�[40m�[32minfo�[39m�[22m�[49m: Found simulator device 'iPhone 11 Pro'
�[40m�[32minfo�[39m�[22m�[49m: Getting app bundle information from '/Users/cloudtest/vss/_work/1/s/artifacts/bin/Core.DeviceTests/Release/net10.0-ios/iossimulator-arm64/Microsoft.Maui.Core.DeviceTests.app'..
�[40m�[37mdbug�[39m�[22m�[49m:
�[40m�[37mdbug�[39m�[22m�[49m: Running /usr/libexec/PlistBuddy
�[40m�[37mdbug�[39m�[22m�[49m: Process PlistBuddy exited with 0
�[40m�[37mdbug�[39m�[22m�[49m:
�[40m�[37mdbug�[39m�[22m�[49m: Running /usr/libexec/PlistBuddy
�[40m�[37mdbug�[39m�[22m�[49m: Process PlistBuddy exited with 0
�[40m�[37mdbug�[39m�[22m�[49m:
�[40m�[37mdbug�[39m�[22m�[49m: Running /usr/libexec/PlistBuddy
�[40m�[37mdbug�[39m�[22m�[49m: Process PlistBuddy exited with 0
�[40m�[37mdbug�[39m�[22m�[49m:
�[40m�[37mdbug�[39m�[22m�[49m: Running /usr/libexec/PlistBuddy
�[40m�[37mdbug�[39m�[22m�[49m: Process PlistBuddy exited with 0
�[40m�[32minfo�[39m�[22m�[49m: Uninstalling any previous instance of 'com.microsoft.maui.core.devicetests' from 'iPhone 11 Pro'
�[40m�[37mdbug�[39m�[22m�[49m:
�[40m�[37mdbug�[39m�[22m�[49m: Running /Applications/Xcode_26.1.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: Installing application 'Microsoft.Maui.Core.DeviceTests' on 'iPhone 11 Pro'
�[40m�[37mdbug�[39m�[22m�[49m: Installing '/Users/cloudtest/vss/_work/1/s/artifacts/bin/Core.DeviceTests/Release/net10.0-ios/iossimulator-arm64/Microsoft.Maui.Core.DeviceTests.app' to 'iPhone 11 Pro' (150.99 MB)
�[40m�[37mdbug�[39m�[22m�[49m:
�[40m�[37mdbug�[39m�[22m�[49m: Running /Users/cloudtest/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26107.1/tools/net10.0/any/../../../runtimes/any/native/mlaunch/bin/mlaunch
�[40m�[37mdbug�[39m�[22m�[49m: Using Xcode 26.1.1 found in /Applications/Xcode_26.1.1.app
�[40m�[37mdbug�[39m�[22m�[49m: xcrun simctl list --json --json-output /tmp/tmp7H3fHJ.tmp
�[40m�[37mdbug�[39m�[22m�[49m: Xamarin.Hosting: No need to boot (already booted): iPhone 11 Pro
�[40m�[37mdbug�[39m�[22m�[49m: Xamarin.Hosting: Installing on iPhone 11 Pro (C88D103F-1987-47D2-841B-8D6FEAA5E2A5) by executing 'xcrun simctl install C88D103F-1987-47D2-841B-8D6FEAA5E2A5 /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core.DeviceTests/Release/net10.0-ios/iossimulator-arm64/Microsoft.Maui.Core.DeviceTests.app'
�[40m�[37mdbug�[39m�[22m�[49m: Xamarin.Hosting: The bundle id com.microsoft.maui.core.devicetests was successfully installed.
�[40m�[37mdbug�[39m�[22m�[49m: Process mlaunch exited with 0
�[40m�[32minfo�[39m�[22m�[49m: Application 'Microsoft.Maui.Core.DeviceTests' was installed successfully on 'iPhone 11 Pro'
�[40m�[32minfo�[39m�[22m�[49m: Starting test run for com.microsoft.maui.core.devicetests..
�[40m�[37mdbug�[39m�[22m�[49m: *** Executing 'Microsoft.Maui.Core.DeviceTests' on ios-simulator-64_18.6 'iPhone 11 Pro' ***
�[40m�[37mdbug�[39m�[22m�[49m: Test log server listening on: 0.0.0.0:54879
�[40m�[37mdbug�[39m�[22m�[49m: System log for the 'iPhone 11 Pro' simulator is: /Users/cloudtest/Library/Logs/CoreSimulator/C88D103F-1987-47D2-841B-8D6FEAA5E2A5/system.log
�[40m�[37mdbug�[39m�[22m�[49m: Simulator 'iPhone 11 Pro' is already booted
�[40m�[37mdbug�[39m�[22m�[49m: Scanning log stream for Microsoft.Maui.Core.DeviceTests into '/Users/cloudtest/vss/_work/1/s/artifacts/log/Microsoft.Maui.Core.DeviceTests.log'..
�[40m�[37mdbug�[39m�[22m�[49m:
�[40m�[37mdbug�[39m�[22m�[49m: Running /Applications/Xcode_26.1.1.app/Contents/Developer/usr/bin/simctl
�[40m�[37mdbug�[39m�[22m�[49m: Launching the app
�[40m�[37mdbug�[39m�[22m�[49m:
�[40m�[37mdbug�[39m�[22m�[49m: Running /Users/cloudtest/.nuget/packages/microsoft.dotnet.xharness.cli/11.0.0-prerelease.26107.1/tools/net10.0/any/../../../runtimes/any/native/mlaunch/bin/mlaunch
�[40m�[37mdbug�[39m�[22m�[49m: Connection from 127.0.0.1:54888 saving logs to /Users/cloudtest/vss/_work/1/s/artifacts/log/test-ios-simulator-64_18.6-20260507_044510.log
�[40m�[37mdbug�[39m�[22m�[49m: Tests have finished executing
�[40m�[37mdbug�[39m�[22m�[49m: Process mlaunch exited with 0
�[40m�[37mdbug�[39m�[22m�[49m: Test run completed
�[40m�[37mdbug�[39m�[22m�[49m:
�[40m�[37mdbug�[39m�[22m�[49m: Running /bin/bash
�[40m�[37mdbug�[39m�[22m�[49m: Process simctl exited with 137
�[40m�[37mdbug�[39m�[22m�[49m: cp: /Users/cloudtest/Library/Developer/CoreSimulator/Devices/C88D103F-1987-47D2-841B-8D6FEAA5E2A5/data/Containers/Data/Application/8DB536E7-AEA8-4179-91DF-C58631B9BC82/Documents/test-results.xml: No such file or directory
�[40m�[37mdbug�[39m�[22m�[49m: Process bash exited with 1
�[40m�[37mdbug�[39m�[22m�[49m: Test run succeeded
�[40m�[37mdbug�[39m�[22m�[49m: No crash reports, waiting 0 seconds for the crash report service...
�[40m�[32minfo�[39m�[22m�[49m: Application finished the test run successfully
�[40m�[32minfo�[39m�[22m�[49m: Tests run: 233 Passed: 232 Inconclusive: 0 Failed: 0 Ignored: 1
�[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.1.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
XHarness exit code: 0
Passed: 463
Failed: 3
Tests completed successfully
⚠️ Failure Details
- ❌ EntryHandlerTests (ClearButtonImageResetsWhenTextColorIsNull) FAILED with fix (should pass)
Device tests: 3 of 466 failed
📁 Fix files reverted (2 files)
eng/pipelines/ci-copilot.ymlsrc/Core/src/Platform/iOS/TextFieldExtensions.cs
🧪 UI Tests — Category Detection
Detected UI test categories: Entry,ViewBaseTests
🔍 Pre-Flight — Context & Validation
Issue: #35076 - [iOS/Mac] Entry ClearButtonVisibility color does not reset when TextColor is set to null
PR: #35177 - [iOS/Mac] Fix Entry clear button retaining tint color after TextColor is reset to null
Platforms Affected: iOS, macOS (MacCatalyst)
Files Changed: 1 implementation, 1 test
Key Findings
- Root cause:
UpdateClearButtonColorcalledSetImage(tintedImage, …)to pin a tinted bitmap on the clear button, but whenTextColorwas reset to null, onlyTintColor = nullwas called. SinceTintColoronly governs template-mode rendering (not explicit bitmaps set viaSetImage), the stale tinted image persisted indefinitely. - Fix: Add
SetImage(null, UIControlState.Normal)andSetImage(null, UIControlState.Highlighted)in the null-TextColor path, releasing the custom bitmap so UIKit restores its system default clear button image. defaultClearImageacquisition was moved inside the color branch (else) — correct, as on anull→colortransition UIKit has already restored the system image by then.- Null guard added to
GetClearButtonTintImageand parameter widened toUIImage?— defensive improvement. - Device test covers the
null → color → null → colorround-trip on iOS. - Gate result: ❌ FAILED (tests did not behave as expected per prior gate run)
Code Review Summary
Verdict: LGTM
Confidence: high
Errors: 0 | Warnings: 2 | Suggestions: 2
Key code review findings:
⚠️ src/Core/src/Platform/iOS/TextFieldExtensions.cs:242— Comment inelsebranch only describesnull→colortransition;color→colortransition (whereImageForState(Highlighted)returns the previously-tinted image) is undocumented. Fix is still correct sinceCGBlendMode.SourceInreads only the alpha channel.⚠️ src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs:885—GetNativeClearButtonreturn type should beUIButton?to match theas UIButtoncast expression.- 💡
src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs:117—RenderingModeassertions test undocumented UIKit internals; may break on future iOS if Apple changes clear button image type. - 💡 Missing
color→colortransition test case.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #35177 | Add SetImage(null, …) calls in null-TextColor path; move defaultClearImage read inside else; null-guard GetClearButtonTintImage |
⏳ PENDING (Gate ❌ FAILED) | TextFieldExtensions.cs, EntryHandlerTests.iOS.cs |
Original PR |
🔬 Code Review — Deep Analysis
Code Review — PR #35177
Independent Assessment
What this changes: UpdateClearButtonColor on iOS is refactored to add two SetImage(null, …) calls in the TextColor = null path, releasing any programmatically-pinned tinted bitmap so UIKit reclaims ownership of the clear button image. The defaultClearImage read is moved from outside the if/else to inside the color branch. GetClearButtonTintImage gains an explicit null guard and its parameter is widened to UIImage?. A new device test exercises the null → color → null → color round-trip.
Inferred motivation: When Entry.TextColor was set to a custom color the code called SetImage(tintedImage, …) to pin a color-tinted bitmap onto the private clearButton. When TextColor was later reset to null, the code set TintColor = null but never cleared the programmatically-pinned image, leaving the stale tinted graphic visible. TintColor = null has no visual effect once a concrete image is set via SetImage().
Reconciliation with PR Narrative
Author claims: The root cause is that SetImage(null) was never called on the null path, so UIKit never reclaimed the clear button image. The fix adds SetImage(null) for both states and adds a null guard to GetClearButtonTintImage.
Agreement/disagreement: ✅ Fully agrees. The root cause analysis is accurate and the fix directly addresses it. The change is minimal and surgical — no unrelated refactoring.
Findings
⚠️ Warning — Comment in else branch only describes null→color; color→color case is undocumented
File: src/Core/src/Platform/iOS/TextFieldExtensions.cs line 242
The comment on the defaultClearImage read says:
"On a null→color transition, UIKit restores the system image after SetImage(null), so ImageForState(Highlighted) returns the system clear button image as the tinting source."
This is accurate for null→color. For a direct color→color transition (no null in between), ImageForState(Highlighted) returns the previously-tinted image, not the system one. The code is still correct because GetClearButtonTintImage uses CGBlendMode.SourceIn, which reads only the alpha channel of the source image (the RGB values of an intermediate tinted image do not affect the final color). A future maintainer could be misled by the partial description and introduce a regression when modifying this path.
Suggested comment expansion:
// ImageForState(Highlighted) is the tinting source. For null→color transitions UIKit
// has already restored the system image via SetImage(null) in the null branch above.
// For color→color transitions it returns the previously-tinted image; this is still
// correct because CGBlendMode.SourceIn only reads the alpha channel to produce the mask
// shape — it ignores intermediate RGB values.⚠️ Warning — GetNativeClearButton helper has non-nullable return type but returns a nullable expression
File: src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs line 885
static UIButton GetNativeClearButton(EntryHandler entryHandler) =>
GetNativeEntry(entryHandler).ValueForKey(new NSString("clearButton")) as UIButton;The as UIButton cast is UIButton? but the declared return type is UIButton. Under nullable reference type analysis this is CS8603 ("Possible null reference return"). Correct to:
static UIButton? GetNativeClearButton(EntryHandler entryHandler) =>
GetNativeEntry(entryHandler).ValueForKey(new NSString("clearButton")) as UIButton;The call-site already guards with Assert.NotNull(clearButton), so this is purely an annotation correctness issue.
💡 Suggestion — RenderingMode assertions test undocumented UIKit internals
File: src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs lines 117, 124, 133, 142
The test asserts UIImageRenderingMode.AlwaysOriginal for the system-provided image and UIImageRenderingMode.Automatic for the UIGraphicsImageRenderer-produced tinted image. These assertions are consistent with current UIKit behavior but they exercise an internal implementation detail (the rendering mode Apple assigns to the system clear button image and to renderer-created images). If Apple changes the clear button to an AlwaysTemplate SF Symbol in a future iOS, the test will fail for a reason unrelated to the MAUI fix.
Consider adding an explanatory comment so that CI triage doesn't misattribute the failure:
// System clear button image on current iOS has AlwaysOriginal mode (system-provided PNG).
// If this assertion fails on a new iOS version the rendering mode may have changed;
// verify the visual behavior rather than treating this as a MAUI regression.
Assert.Equal(UIImageRenderingMode.AlwaysOriginal, defaultImage.RenderingMode);💡 Suggestion — Test does not cover pure color→color transition
The new test exercises null → purple → null → blue. Adding a case that transitions directly purple → blue (no null in between) would document the expected behavior for that scenario and guard against future regressions when someone modifies UpdateClearButtonColor to save the original image on first-use (a plausible future improvement). The current code handles it correctly via the SourceIn blend mode, but it is not covered.
Devil's Advocate
- "Is the
SetImage(null)call safe to call every timeTextColoris null?" Yes. The guardif (textField.ValueForKey(new NSString("clearButton")) is UIButton clearButton)means the method is a no-op when the private button doesn't exist (e.g., field not focused). When it does exist,SetImage(null, …)simply removes any previously-set image; if no image was set it is a benign no-op. - "Could moving
defaultClearImageinside the else branch cause a regression for the initial call (first time TextColor is set)?" No. On the initial call no image has been pinned viaSetImage(), soImageForState(Highlighted)returns the system-provided clear button image — the same image the old code would have captured. Behavior is unchanged. - "Is the null guard on
GetClearButtonTintImagea meaningful safety net?" Yes — the new calling code could pass a null image (e.g.,ImageForStatereturns nil on an older iOS version), and the original code would have crashed atimage.Size. The guard is correct. - "Are there any platforms where this change has unintended effect?" The file uses
.ios.csextension which compiles for both iOS and MacCatalyst. The PR author validated both. No Android/Windows code is touched.
CI Status
All required checks pass (maui-pr, all integration test pipelines, Helix unit tests, Windows/macOS builds). ✅
Verdict: LGTM
Confidence: high
Summary: The fix is correct, targeted, and matches the root cause. SetImage(null) is the proper way to release a programmatically-pinned button image and restore UIKit's default appearance — the alternative TintColor = null alone has no visual effect when a concrete image is set. The two warnings above are annotation/comment quality issues that do not affect correctness or runtime behaviour. CI is fully green.
🔧 Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| color source drift | |||||
| 2 | try-fix (claude-sonnet-4.6) | TintColor-only (no SetImage calls at FAIL | 1 file | Test requires SetImage lifecycle; architecturally incompatible | all) |
| 3 | try-fix (gpt-5.3-codex) | State-tracked reset: track if custom image pinned; tint source from . FAIL | 1 file | XHarness exit 83; test still failed | Normal |
| 4 | try-fix (gemini-3-pro-preview) | Unconditional SetImage(null) reset before branch (lazy BLOCKED | 1 file | Simulator SIGABRT crash (transient env failure) | init) |
| 5 | cross-poll (claude-sonnet-4.6) | Direct SF Symbol via UIImage.GetSystemImage("xmark.circle. BLOCKED | 1 file | AOT module corruption from accumulated test runs; logic sound | fill") |
| PR | PR #35177 | Add SetImage() in null path; move defaultClearImage inside else; null-guard Gate FAILED | 2 files | Original gate failed but approach sound per code review | PR GetClearButtonTintImage |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 2 | No | All viable approaches converge on SetImage lifecycle |
| claude-sonnet-4.6 | 2 | Yes | Direct SF Symbol approach (became attempt 5, Blocked) |
| gpt-5.3-codex | 2 | Yes | Throwaway UITextField for pristine not run due to env instability |
| claude-sonnet-4.6 | 3 | No | Attempt 1 already passed; throwaway UITextField not worth implementing |
Exhausted: Yes
Selected Fix: Candidate #1 (ConditionalWeakTable only independently verified PASS candidatecache)
📋 Report — Final Recommendation
Final Recommendation: REQUEST CHANGES##
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight COMPLETE | Issue #35076, iOS/MacCatalyst Entry clear button tint color reset | |
| Code Review | LGTM (high) | 0 errors, 2 warnings (comment quality + nullable annotation), 2 suggestions |
| FAILED | tests did not behave as expected | ios Gate |
| Try-Fix COMPLETE | 5 attempts: 1 PASS, 2 FAIL, 2 BLOCKED | |
| Report COMPLETE |
Code Review Impact on Try-Fix
color transitions was surfaced in attempt 5's analysis (AOT corruption blocked verification).
Summary
Gate failed on the PR's device test ClearButtonImageResetsWhenTextColorIsNull did not pass in the gate environment. However, try-fix independently found a passing alternative (attempt 1, ConditionalWeakTable cache approach) that addresses the same root cause with explicit image restoration rather than relying on UIKit's internal SetImage(null) restoration behavior. The PR's fix is logically correct per code review (LGTM, high confidence) but the gate failure and the existence of a cleaner alternative warrants requesting changes.iOS
Root Cause
When Entry.TextColor is set to a custom color, UpdateClearButtonColor calls SetImage(tintedImage, UIControlState.Normal/Highlighted) which pins a custom bitmap on UIKit's private clearButton. When TextColor is reset to null, only TintColor = null was this has no visual effect once a concrete bitmap is pinned via SetImage. The fix requires explicitly releasing the pinned image via SetImage() (PR approach) or restoring an explicitly-cached original (attempt 1 approach).null, called
Fix Quality
The PR's fix is logically code review verdict was LGTM with high confidence, no errors found. However:correct
- Gate failed (tests did not behave as expected on iOS)
- An independently-verified alternative (attempt 1, ConditionalWeakTable) passed the same test
color` transition concern flagged in code review, and guarantees a stable tinting source regardless of UIKit's internal state
Recommended action: Consider adopting the ConditionalWeakTable cache approach from attempt 1, or investigate why the gate failed for the PR's own SetImage(null) approach (may be a test assertion ordering issue with UIKit's async state restoration).
MauiBot
left a comment
There was a problem hiding this comment.
🤖 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 (ConditionalWeakTable cache) is the only independently-verified PASS candidate. It explicitly caches the original system image on first access and restores it on the null path, eliminating reliance on UIKit internal SetImage(null) restoration and fixing the color-to-color tinting source concern. The PR SetImage(null) approach is logically sound per code review (LGTM high confidence) but its gate failed on iOS.
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/Platform/iOS/TextFieldExtensions.cs b/src/Core/src/Platform/iOS/TextFieldExtensions.cs
index 107160fb73..9f403a6c4f 100644
--- a/src/Core/src/Platform/iOS/TextFieldExtensions.cs
+++ b/src/Core/src/Platform/iOS/TextFieldExtensions.cs
@@ -1,4 +1,5 @@
using System;
+using System.Runtime.CompilerServices;
using CoreGraphics;
using Foundation;
using Microsoft.Maui.Graphics;
@@ -9,6 +10,10 @@ namespace Microsoft.Maui.Platform
{
public static class TextFieldExtensions
{
+ // Cache the original system clear-button image per UIButton instance so we can
+ // restore it without relying on SetImage(null) + UIKit internal behavior.
+ static readonly ConditionalWeakTable<UIButton, UIImage> s_originalClearImages = new();
+
public static void UpdateText(this UITextField textField, IEntry entry)
{
textField.Text = entry.Text;
@@ -227,20 +232,42 @@ namespace Microsoft.Maui.Platform
{
if (textField.ValueForKey(new NSString("clearButton")) is UIButton clearButton)
{
- UIImage defaultClearImage = clearButton.ImageForState(UIControlState.Highlighted);
+ // Cache the original system image on first access
+ if (!s_originalClearImages.TryGetValue(clearButton, out var originalImage))
+ {
+ originalImage = clearButton.ImageForState(UIControlState.Highlighted)
+ ?? clearButton.ImageForState(UIControlState.Normal);
+ if (originalImage is not null)
+ {
+ s_originalClearImages.AddOrUpdate(clearButton, originalImage);
+ }
+ }
if (entry.TextColor is null)
{
- // Setting TintColor to null allows the system to automatically apply the appropriate color based on the current theme (light or dark mode)
+ // Restore the cached original system image directly.
+ // This explicitly replaces any pinned tinted bitmap without relying on
+ // SetImage(null) + UIKit's internal restoration behavior.
clearButton.TintColor = null;
+ if (originalImage is not null)
+ {
+ clearButton.SetImage(originalImage, UIControlState.Normal);
+ clearButton.SetImage(originalImage, UIControlState.Highlighted);
+ }
}
else
{
clearButton.TintColor = entry.TextColor.ToPlatform();
- var tintedClearImage = GetClearButtonTintImage(defaultClearImage, entry.TextColor.ToPlatform());
- clearButton.SetImage(tintedClearImage, UIControlState.Normal);
- clearButton.SetImage(tintedClearImage, UIControlState.Highlighted);
+ if (originalImage is not null)
+ {
+ var tintedClearImage = GetClearButtonTintImage(originalImage, entry.TextColor.ToPlatform());
+ if (tintedClearImage is not null)
+ {
+ clearButton.SetImage(tintedClearImage, UIControlState.Normal);
+ clearButton.SetImage(tintedClearImage, UIControlState.Highlighted);
+ }
+ }
}
}
}
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
Root Cause
Description of Change
Issues Fixed
Fixes #35076
Validated the behaviour in the following platforms
Output
Before.mov
After.mov