[iOS,MacCatalyst] Fix for SwipeView.Open() throwing an ArgumentException on the second programmatic call#34982
Conversation
…ption on the second programmatic call for RightItems/BottomItems on iOS/Mac Catalyst.
|
🚀 Dogfood this PR with:
curl -fsSL https://github.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34982Or
iex "& { $(irm https://github.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34982" |
🚦 Gate — Test Before and After Fix
🚦 Gate Session —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ Issue34917 Issue34917 |
✅ FAIL — 224s | ✅ PASS — 97s |
🔴 Without fix — 🖥️ Issue34917: FAIL ✅ · 224s
Determining projects to restore...
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 557 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 654 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 12.14 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 15.53 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 15.54 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 15.55 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 15.56 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 15.56 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 15.58 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 15.56 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/maps/src/Maps.csproj (in 15.58 sec).
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
Detected signing identity:
Code Signing Key: "" (-)
Provisioning Profile: "" () - no entitlements
Bundle Id: com.microsoft.maui.uitests
App Id: com.microsoft.maui.uitests
Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.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.
Build succeeded.
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
1 Warning(s)
0 Error(s)
Time Elapsed 00:01:41.78
Determining projects to restore...
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 666 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 672 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 667 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 676 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 0.9 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 693 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 745 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 360 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 1.46 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 2.73 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 3.94 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 7.88 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.iOS.Tests/Controls.TestCases.iOS.Tests.csproj (in 7.9 sec).
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.04] Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.13] Discovered: Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
NUnit3TestExecutor discovered 2 of 2 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 4/15/2026 1:03:55 PM FixtureSetup for Issue34917(iOS)
>>>>> 4/15/2026 1:04:00 PM SwipeViewOpenBottomDoesNotThrowOnSecondCall Start
>>>>> 4/15/2026 1:04:02 PM SwipeViewOpenBottomDoesNotThrowOnSecondCall Stop
>>>>> 4/15/2026 1:04:02 PM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
Failed SwipeViewOpenBottomDoesNotThrowOnSecondCall [2 s]
Error Message:
Second consecutive Open(BottomItems) call should not throw an exception.
Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"))
Expected string length 7 but was 24. Strings differ at index 0.
Expected: "Success"
But was: "Error: ArgumentException"
-----------^
Stack Trace:
at Microsoft.Maui.TestCases.Tests.Issues.Issue34917.SwipeViewOpenBottomDoesNotThrowOnSecondCall() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs:line 43
1) at Microsoft.Maui.TestCases.Tests.Issues.Issue34917.SwipeViewOpenBottomDoesNotThrowOnSecondCall() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs:line 43
>>>>> 4/15/2026 1:04:02 PM SwipeViewOpenRightDoesNotThrowOnSecondCall Start
>>>>> 4/15/2026 1:04:04 PM SwipeViewOpenRightDoesNotThrowOnSecondCall Stop
>>>>> 4/15/2026 1:04:04 PM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
Failed SwipeViewOpenRightDoesNotThrowOnSecondCall [1 s]
Error Message:
Second consecutive Open(RightItems) call should not throw an exception.
Assert.That(App.FindElement(StatusLabelId).GetText(), Is.EqualTo("Success"))
Expected string length 7 but was 24. Strings differ at index 0.
Expected: "Success"
But was: "Error: ArgumentException"
-----------^
Stack Trace:
at Microsoft.Maui.TestCases.Tests.Issues.Issue34917.SwipeViewOpenRightDoesNotThrowOnSecondCall() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs:line 25
1) at Microsoft.Maui.TestCases.Tests.Issues.Issue34917.SwipeViewOpenRightDoesNotThrowOnSecondCall() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs:line 25
NUnit Adapter 4.5.0.0: Test execution complete
Total tests: 2
Failed: 2
Test Run Failed.
Total time: 1.0706 Minutes
🟢 With fix — 🖥️ Issue34917: PASS ✅ · 97s
Determining projects to restore...
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 395 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 407 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 413 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 441 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 453 ms).
6 of 11 projects are up-to-date for restore.
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
Detected signing identity:
Code Signing Key: "" (-)
Provisioning Profile: "" () - no entitlements
Bundle Id: com.microsoft.maui.uitests
App Id: com.microsoft.maui.uitests
Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.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.
Build succeeded.
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
1 Warning(s)
0 Error(s)
Time Elapsed 00:00:48.18
Determining projects to restore...
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 333 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 388 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 384 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 396 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 419 ms).
8 of 13 projects are up-to-date for restore.
Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.13847611
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.05] Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.17] Discovered: Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
NUnit3TestExecutor discovered 2 of 2 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 4/15/2026 1:05:32 PM FixtureSetup for Issue34917(iOS)
>>>>> 4/15/2026 1:05:37 PM SwipeViewOpenBottomDoesNotThrowOnSecondCall Start
>>>>> 4/15/2026 1:05:39 PM SwipeViewOpenBottomDoesNotThrowOnSecondCall Stop
Passed SwipeViewOpenBottomDoesNotThrowOnSecondCall [2 s]
>>>>> 4/15/2026 1:05:39 PM SwipeViewOpenRightDoesNotThrowOnSecondCall Start
>>>>> 4/15/2026 1:05:41 PM SwipeViewOpenRightDoesNotThrowOnSecondCall Stop
Passed SwipeViewOpenRightDoesNotThrowOnSecondCall [1 s]
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Successful.
Total tests: 2
Passed: 2
Total time: 21.7441 Seconds
📁 Fix files reverted (1 files)
src/Core/src/Platform/iOS/MauiSwipeView.cs
🤖 AI Summary
📊 Review Session —
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #34982 | (1) Remove Math.Abs(_swipeOffset) in ProgrammaticallyOpenSwipeItem; (2) Add _swipeItems.Clear() in UpdateSwipeItems | ✅ PASSED (Gate) | MauiSwipeView.cs |
Original PR |
🔬 Code Review — Deep Analysis
Code Review — PR #34982
Independent Assessment
What this changes:
MauiSwipeView.cs: Adds_swipeItems.Clear()at the start ofUpdateSwipeItems(), and removes_swipeOffset = Math.Abs(_swipeOffset)from the end ofProgrammaticallyOpenSwipeItem().- Two new test files adding a UI test page and the corresponding NUnit test class for the SwipeView open scenario.
Inferred motivation (from code alone):
UpdateSwipeItems() calls _swipeItems.Add(item, swipeItem) for each swipe item. Dictionary.Add() throws ArgumentException on duplicate keys. If _swipeItems somehow retained stale entries between calls, the second UpdateSwipeItems would crash.
Tracing _swipeOffset = Math.Abs(_swipeOffset) at the end of ProgrammaticallyOpenSwipeItem: after UpdateOffset() sets _swipeOffset to -swipeThreshold for Left/Up directions, Math.Abs makes it positive. Then, on the next LayoutSubviews → Swipe(false) call, ValidateSwipeOffset has this guard for SwipeDirection.Left:
case SwipeDirection.Left:
if (offset > 0)
offset = 0; // positive offset clamped to zero!This silently resets _isOpen = (0 != 0) = false, without calling DisposeSwipeItems(), leaving _swipeItems populated but _isOpen falsely reporting closed. On the second ProgrammaticallyOpenSwipeItem call, the _isOpen == false guard does not return early, UpdateSwipeItems() runs again, and _swipeItems.Add throws on duplicate keys. This is the exact crash chain.
Is the approach sound?
Yes. Both changes are necessary and complementary:
- Removing
Math.Absis the root cause fix: preserves the correct signed offset soValidateSwipeOffsetproduces the expected non-zero result, keeping_isOpen = truestable across layout passes. - Adding
_swipeItems.Clear()is the defensive fix: guards against any future path that reachesUpdateSwipeItems()without having cleared the dictionary first. The existing manual-swipe path (ProcessTouchMove) already callsResetSwipeToInitialPosition → DisposeSwipeItems → _swipeItems.Clear()beforeUpdateSwipeItems(), so this adds no behavioral change for that path.
Reconciliation with PR Narrative
Author claims: Math.Abs corrupts the negative offset required for Left/Up swipe directions, causing ValidateSwipeOffset to clamp to zero, which resets _isOpen without clearing _swipeItems, leading to duplicate keys on the second call.
Agreement: Complete agreement. The chain I traced independently matches the PR description exactly. The description is precise and technically correct.
One note: The PR author and the issue reporter are the same GitHub user (BagavathiPerumal). The PR is also in draft state, so this review is pre-merge feedback.
Findings
💡 Suggestion — Consider adding a Close → Reopen test to guard adjacent scenario
SwipeViewOpenRightDoesNotThrowOnSecondCall tests two consecutive Opens without closing (the direct bug scenario). A complementary test covering Open → Close → Open would guard the adjacent path where DisposeSwipeItems runs between calls — particularly valuable since this file now lives next to the SwipeView regression history. The Close → Reopen path uses different code: _isOpen == false AND _swipeItems is freshly cleared, which is the "happy path" that the bug indirectly masked.
This isn't a blocker — the reported bug is correctly covered — but it closes a gap in scenario coverage that the regression history for this component warrants.
Devil's Advocate
Challenge: Is _swipeItems.Clear() hiding a deeper problem?
If _swipeItems has stale entries when UpdateSwipeItems is called (outside the Math.Abs bug path), it means a caller didn't go through DisposeSwipeItems. The Clear() fixes the symptom but lets the caller off the hook. However, examining all call sites: the only two callers are ProcessTouchMove (always calls DisposeSwipeItems first) and ProgrammaticallyOpenSwipeItem (whose bug path is now fixed by the Math.Abs removal). The Clear() is therefore genuinely defensive, not a symptom masker, and its cost is O(n) on a small dictionary.
Challenge: Could removing Math.Abs break anything?
_swipeOffset is read by ValidateSwipeOffset, TouchesEnded (!= 0 check), and HandlePan's != 0 check — none of which care about the sign being forced positive. The signed value is exactly what ValidateSwipeOffset expects. No breakage identified.
Challenge: Are the tests reliable?
The App.Tap(CloseButtonId) at the start of SwipeViewOpenBottomDoesNotThrowOnSecondCall looks odd in isolation, but it's valid test isolation — if SwipeViewOpenRightDoesNotThrowOnSecondCall ran first and left the swipe open, the Close tap resets state before the Bottom test. This is correct defensive test sequencing.
Platform scope: The changed file (src/Core/src/Platform/iOS/MauiSwipeView.cs) compiles for iOS and MacCatalyst only. Android and Windows are unaffected. The PR's platform checklist correctly leaves Windows/Android unchecked. The UI test uses PlatformAffected.iOS | PlatformAffected.macOS on the host page but the NUnit class carries no platform exclusion — it will run on all platforms, which is fine since it tests an exception-free scenario that passes trivially on unaffected platforms.
Blast Radius Assessment
Scope: Changes are limited to ProgrammaticallyOpenSwipeItem and UpdateSwipeItems in MauiSwipeView.cs.
Math.Absremoval only affects programmatic open calls (not gesture-driven swipes, which never callProgrammaticallyOpenSwipeItem)_swipeItems.Clear()runs every timeUpdateSwipeItemsis called — both programmatic and gesture paths — but since the dictionary is always populated fresh immediately after, the cost is clearing an already-correct dictionary on the gesture path- Platform scope: iOS and MacCatalyst only
- No cross-platform regression risk
Verdict: LGTM
Confidence: High
Summary: The root cause is correctly identified and precisely fixed. Both code changes are necessary: Math.Abs removal is the primary fix (prevents _isOpen from being silently reset), and _swipeItems.Clear() is a sound defensive addition. The tests cover the exact reported scenario, and no regressions to adjacent SwipeView behavior were identified.
🔧 Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix (claude-opus-4.6) | Use dictionary indexer instead of in UpdateSwipeItems; add before creating new UIStackView | PASS | MauiSwipeView.cs (+5/-1) |
Symptom fix leaves Math.Abs root cause in place |
| 2 | try-fix (claude-sonnet-4.6) | Remove ONLY PASS | MauiSwipeView.cs (+0/-2) |
Minimal root-cause fix; proves single-line removal is sufficient | |
| 3 | try-fix (gpt-5.3-codex) | In Swipe(), call DisposeSwipeItems() when `!_isOpen && !_isSwiping && !_isResettingSwipe && _swipeItems.Count > PASS |
MauiSwipeView.cs (+7/-0) |
State-consistency fix; more invasive touch point in Swipe() | 0` |
| 4 | try-fix (gpt-5.4) | In ProgrammaticallyOpenSwipeItem, add if (!_isOpen && _swipeItems.Count > 0) ResetSwipe(false) guard before PASS |
MauiSwipeView.cs (+3/-0) |
API-boundary guard; broader reset side effects | proceeding |
| PR | PR #34982 | (1) Remove Math.Abs(_swipeOffset) in ProgrammaticallyOpenSwipeItem; (2) Add _swipeItems.Clear() in UpdateSwipeItems PASSED (Gate) | MauiSwipeView.cs |
Root cause fix + defensive best combination | clear |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 2 | No | "NO NEW design space covered by 5 attempts" |
Exhausted: Yes
Selected Fix: PR # Removes the root cause (Math.Abs) AND adds a defensive _swipeItems.Clear() that guards against any future path where UpdateSwipeItems is called with stale entries. Attempt 2 shows the single-line removal is technically sufficient, but the PR's combination is more robust. The Clear() has zero behavioral impact on existing gesture paths (they always go through DisposeSwipeItems first) and costs O(n) on a small dictionary.34982
📋 Report — Final Recommendation
✅ Final Recommendation: APPROVE
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | ✅ COMPLETE | Issue #34917, iOS/MacCatalyst, 1 impl file + 2 test files |
| Code Review | ✅ LGTM (high confidence) | 0 errors, 0 warnings, 1 suggestion (non-blocking) |
| Gate | ✅ PASSED | ios — tests FAIL without fix, PASS with fix |
| Try-Fix | ✅ COMPLETE | 4 attempts, 4 passing (+ PR); exploration exhausted |
| Report | ✅ COMPLETE |
Code Review Impact on Try-Fix
Code review found no errors or warnings — verdict was LGTM with high confidence. With no blocking findings to address, try-fix models were free to explore the full fix design space independently. The one 💡 suggestion (adding an Open→Close→Reopen test) was informational and did not guide any attempt toward a different fix strategy. All 4 models confirmed the fix is sound from different angles, reinforcing the code review's LGTM verdict.
Summary
PR #34982 correctly identifies and fixes a long-standing iOS/MacCatalyst bug where calling SwipeView.Open() programmatically more than once with the same direction throws ArgumentException: An item with the same key has already been added. The fix is minimal, precise, and well-tested. Four independent fix attempts all passed, and all models confirmed no new approaches remained unexplored.
Root Cause
ProgrammaticallyOpenSwipeItem called _swipeOffset = Math.Abs(_swipeOffset) after Swipe(animated). For Left/Up swipe directions (used by RightItems and BottomItems respectively), UpdateOffset correctly sets _swipeOffset to a negative value. Math.Abs then strips the sign, making it positive. On the next layout pass, ValidateSwipeOffset clamps any positive offset to 0 for Left/Up directions — silently setting _isOpen = false — without ever calling DisposeSwipeItems(). On the second Open() call, _swipeItems still has entries from the first call, and UpdateSwipeItems().Add() throws on duplicate keys.
Fix Quality
The PR's two-part fix is the best among all candidates:
-
Remove
Math.Abs(_swipeOffset)— the true root cause fix. Attempt 2 confirmed this single-line removal alone is sufficient to pass all tests. No edge case where keeping it would be correct was identified. -
Add
_swipeItems.Clear()inUpdateSwipeItems()— a sound defensive addition. The gesture-driven path always callsDisposeSwipeItems(which clears the dictionary) beforeUpdateSwipeItems, so thisClear()has no behavioral impact on normal gesture flows. It costs O(n) on a small dictionary and guards against any future code path that might reachUpdateSwipeItemswithout prior cleanup.
Compared to the alternatives found by Try-Fix:
- Attempt 1 (dictionary indexer): Masks the symptom without fixing the root cause. Math.Abs remains.
- Attempt 3 (DisposeSwipeItems in Swipe()): Valid but adds side effects (early return from Swipe) at a lower-level touch point.
- Attempt 4 (ResetSwipe guard in ProgrammaticallyOpenSwipeItem): Valid but ResetSwipe() resets more state (including _swipeThreshold, _swipeDirection) which may have subtler behavioral differences.
The PR's combination is the cleanest: remove the bug (Math.Abs) and add a guard (Clear) exactly where UpdateSwipeItems is populated.
One non-blocking suggestion from code review: Adding an Open→Close→Reopen test would guard the DisposeSwipeItems path between calls. Not required for merge, but worthwhile for completeness given this component's regression history.
There was a problem hiding this comment.
Pull request overview
Fixes an iOS/MacCatalyst SwipeView regression where calling SwipeView.Open() programmatically multiple times can throw ArgumentException due to inconsistent swipe offset/state, and adds a UI test to prevent regressions.
Changes:
- Preserve directional
_swipeOffsetduring programmatic opens by removing an incorrectMath.Absnormalization. - Add a defensive
_swipeItems.Clear()before repopulating swipe item views duringUpdateSwipeItems(). - Add a new HostApp repro page and corresponding Appium/NUnit UI tests for issue #34917.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/Core/src/Platform/iOS/MauiSwipeView.cs | Fixes programmatic open offset sign handling and defensively resets swipe item mapping before rebuilding. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34917.cs | Adds UI tests verifying repeated programmatic Open() calls don’t throw for Right/Bottom items. |
| src/Controls/tests/TestCases.HostApp/Issues/Issue34917.cs | Adds a HostApp issue page with buttons that reproduce the repeated Open() scenario and report success/failure via a label. |
Comments suppressed due to low confidence (1)
src/Core/src/Platform/iOS/MauiSwipeView.cs:320
- UpdateSwipeItems() clears _swipeItems, but it still unconditionally creates a new _actionView and calls AddSubview(_actionView) without removing any existing action view. If UpdateSwipeItems gets invoked multiple times without DisposeSwipeItems/ResetSwipe (which this change is trying to tolerate), old action views can be left in the view hierarchy and overlap/consume memory. Consider removing the existing _actionView from its superview (and clearing related state) before creating/adding a new one, or route through DisposeSwipeItems when rebuilding.
_swipeItemsRect = new List<CGRect>();
_swipeItems.Clear();
double swipeItemsWidth;
if (_swipeDirection == SwipeDirection.Left || _swipeDirection == SwipeDirection.Right)
swipeItemsWidth = items.Count * SwipeViewExtensions.SwipeItemWidth;
else
swipeItemsWidth = _contentView.Frame.Width;
_actionView = new UIStackView
{
Axis = UILayoutConstraintAxis.Horizontal,
Frame = new CGRect(0, 0, swipeItemsWidth, _contentView.Frame.Height)
};
foreach (var item in items)
{
UIView swipeItem = item.ToPlatform(Element.Handler.MauiContext);
_actionView.AddSubview(swipeItem);
_swipeItems.Add(item, swipeItem);
}
AddSubview(_actionView);
|
/azp run maui-pr-uitests , maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
…ion on the second programmatic call (dotnet#34982) <!-- 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! ### Issue Details The issue occurs when calling the SwipeView.Open() method programmatically multiple times on iOS and MacCatalyst platforms. The first call to open swipe items (such as RightItems or BottomItems) works as expected, but the second call throws a System.ArgumentException with the message “An item with the same key has already been added.” This behavior is specific to certain swipe directions that rely on negative offsets (such as right and bottom swipe actions), where the swipe interaction briefly appears and then resets unexpectedly. As a result, internal state inconsistencies lead to a crash during subsequent calls. ### Root Cause The issue occur because of an incorrect use of Math.Abs on the _swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method. This operation removes the negative sign required for specific swipe directions (such as left or up), causing the offset to become invalid during layout validation. Due to this invalid offset, the swipe view resets to a closed state while still retaining previously added entries in the _swipeItems dictionary. When Open() is called again, the same keys are added again to the dictionary, resulting in a duplicate key exception. ### Description of Change The fix involves removing the Math.Abs operation on _swipeOffset to preserve the correct directional value required for swipe behavior, ensuring that the swipe state remains consistent after layout validation. Additionally, a defensive improvement is introduced by clearing the _swipeItems dictionary before repopulating it in the UpdateSwipeItems() method. This prevents duplicate key insertion and ensures that the method behaves safely even if invoked multiple times under unexpected conditions. ### Issues Fixed Fixes dotnet#34917 ### Validated the behaviour in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Before | After | |----------|----------| | <video src="https://github.com/user-attachments/assets/55a131cb-6ccc-4776-80d7-90655651565d"> | <video src="https://github.com/user-attachments/assets/5efc010e-04ec-4e4d-8729-d43f41d2d6bf"> |
…ion on the second programmatic call (#34982) <!-- 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! ### Issue Details The issue occurs when calling the SwipeView.Open() method programmatically multiple times on iOS and MacCatalyst platforms. The first call to open swipe items (such as RightItems or BottomItems) works as expected, but the second call throws a System.ArgumentException with the message “An item with the same key has already been added.” This behavior is specific to certain swipe directions that rely on negative offsets (such as right and bottom swipe actions), where the swipe interaction briefly appears and then resets unexpectedly. As a result, internal state inconsistencies lead to a crash during subsequent calls. ### Root Cause The issue occur because of an incorrect use of Math.Abs on the _swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method. This operation removes the negative sign required for specific swipe directions (such as left or up), causing the offset to become invalid during layout validation. Due to this invalid offset, the swipe view resets to a closed state while still retaining previously added entries in the _swipeItems dictionary. When Open() is called again, the same keys are added again to the dictionary, resulting in a duplicate key exception. ### Description of Change The fix involves removing the Math.Abs operation on _swipeOffset to preserve the correct directional value required for swipe behavior, ensuring that the swipe state remains consistent after layout validation. Additionally, a defensive improvement is introduced by clearing the _swipeItems dictionary before repopulating it in the UpdateSwipeItems() method. This prevents duplicate key insertion and ensures that the method behaves safely even if invoked multiple times under unexpected conditions. ### Issues Fixed Fixes #34917 ### Validated the behaviour in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Before | After | |----------|----------| | <video src="https://github.com/user-attachments/assets/55a131cb-6ccc-4776-80d7-90655651565d"> | <video src="https://github.com/user-attachments/assets/5efc010e-04ec-4e4d-8729-d43f41d2d6bf"> |
|
Will this change be available in .NET 10 SR6 or later service releases? |
…ion on the second programmatic call (#34982) <!-- 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! ### Issue Details The issue occurs when calling the SwipeView.Open() method programmatically multiple times on iOS and MacCatalyst platforms. The first call to open swipe items (such as RightItems or BottomItems) works as expected, but the second call throws a System.ArgumentException with the message “An item with the same key has already been added.” This behavior is specific to certain swipe directions that rely on negative offsets (such as right and bottom swipe actions), where the swipe interaction briefly appears and then resets unexpectedly. As a result, internal state inconsistencies lead to a crash during subsequent calls. ### Root Cause The issue occur because of an incorrect use of Math.Abs on the _swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method. This operation removes the negative sign required for specific swipe directions (such as left or up), causing the offset to become invalid during layout validation. Due to this invalid offset, the swipe view resets to a closed state while still retaining previously added entries in the _swipeItems dictionary. When Open() is called again, the same keys are added again to the dictionary, resulting in a duplicate key exception. ### Description of Change The fix involves removing the Math.Abs operation on _swipeOffset to preserve the correct directional value required for swipe behavior, ensuring that the swipe state remains consistent after layout validation. Additionally, a defensive improvement is introduced by clearing the _swipeItems dictionary before repopulating it in the UpdateSwipeItems() method. This prevents duplicate key insertion and ensures that the method behaves safely even if invoked multiple times under unexpected conditions. ### Issues Fixed Fixes #34917 ### Validated the behaviour in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Before | After | |----------|----------| | <video src="https://github.com/user-attachments/assets/55a131cb-6ccc-4776-80d7-90655651565d"> | <video src="https://github.com/user-attachments/assets/5efc010e-04ec-4e4d-8729-d43f41d2d6bf"> |
…ion on the second programmatic call (#34982) <!-- 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! ### Issue Details The issue occurs when calling the SwipeView.Open() method programmatically multiple times on iOS and MacCatalyst platforms. The first call to open swipe items (such as RightItems or BottomItems) works as expected, but the second call throws a System.ArgumentException with the message “An item with the same key has already been added.” This behavior is specific to certain swipe directions that rely on negative offsets (such as right and bottom swipe actions), where the swipe interaction briefly appears and then resets unexpectedly. As a result, internal state inconsistencies lead to a crash during subsequent calls. ### Root Cause The issue occur because of an incorrect use of Math.Abs on the _swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method. This operation removes the negative sign required for specific swipe directions (such as left or up), causing the offset to become invalid during layout validation. Due to this invalid offset, the swipe view resets to a closed state while still retaining previously added entries in the _swipeItems dictionary. When Open() is called again, the same keys are added again to the dictionary, resulting in a duplicate key exception. ### Description of Change The fix involves removing the Math.Abs operation on _swipeOffset to preserve the correct directional value required for swipe behavior, ensuring that the swipe state remains consistent after layout validation. Additionally, a defensive improvement is introduced by clearing the _swipeItems dictionary before repopulating it in the UpdateSwipeItems() method. This prevents duplicate key insertion and ensures that the method behaves safely even if invoked multiple times under unexpected conditions. ### Issues Fixed Fixes #34917 ### Validated the behaviour in the following platforms - [ ] Windows - [ ] Android - [x] iOS - [x] Mac ### Output | Before | After | |----------|----------| | <video src="https://github.com/user-attachments/assets/55a131cb-6ccc-4776-80d7-90655651565d"> | <video src="https://github.com/user-attachments/assets/5efc010e-04ec-4e4d-8729-d43f41d2d6bf"> |
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
The issue occurs when calling the SwipeView.Open() method programmatically multiple times on iOS and MacCatalyst platforms. The first call to open swipe items (such as RightItems or BottomItems) works as expected, but the second call throws a System.ArgumentException with the message “An item with the same key has already been added.”
This behavior is specific to certain swipe directions that rely on negative offsets (such as right and bottom swipe actions), where the swipe interaction briefly appears and then resets unexpectedly. As a result, internal state inconsistencies lead to a crash during subsequent calls.
Root Cause
The issue occur because of an incorrect use of Math.Abs on the _swipeOffset value inside the ProgrammaticallyOpenSwipeItem()method. This operation removes the negative sign required for specific swipe directions (such as left or up), causing the offset to become invalid during layout validation.
Due to this invalid offset, the swipe view resets to a closed state while still retaining previously added entries in the _swipeItems dictionary. When Open() is called again, the same keys are added again to the dictionary, resulting in a duplicate key exception.
Description of Change
The fix involves removing the Math.Abs operation on _swipeOffset to preserve the correct directional value required for swipe behavior, ensuring that the swipe state remains consistent after layout validation.
Additionally, a defensive improvement is introduced by clearing the _swipeItems dictionary before repopulating it in the UpdateSwipeItems() method. This prevents duplicate key insertion and ensures that the method behaves safely even if invoked multiple times under unexpected conditions.
Issues Fixed
Fixes #34917
Validated the behaviour in the following platforms
Output
34917-BeforeFix.mov
34917-AfterFix.mov