Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

[Bug] ArgumentOutOfRangeException on iOS when removing last item from a collection view with an observable ItemsSource #14171

Open
mediabounds opened this issue Apr 16, 2021 · 6 comments
Labels

Comments

@mediabounds
Copy link

Description

There is a regression in XF 5 on iOS where removing the last item in an observable collection which is serving as the ItemSource for a collection view will cause a crash due to an ArgumentOutOfRangeException. Specifically, the regression was introduced in 5.0.0.1874 by this change:
2dfbf5f

This changeset modified ObservableItemsSource.CollectionChanged and added the following line:

CollectionView.NumberOfItemsInSection(_section);

But this is happening before the internal state of ObservableItemsSource is updated--namely ItemCount. This is problematic because checking the number of items in the section will indirectly invoke ItemsViewController.CheckForEmptySource which checks ItemsSource.ItemCount--since this property hasn't been updated yet, it causes two problems:

  1. When adding the first item to the collection, the empty view will still be visible (because ItemCount will still be 0)
  2. When removing the last item from the collection, ItemCount will still be 1 which will ultimately lead to an attempt to determine the cell size which will attempt to access the first item in an empty collection (causing the ArgumentOutOfRangeException).

Here's an example of the stack trace of the crash:

Unhandled managed exception: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index (System.ArgumentOutOfRangeException)
  at System.Collections.Generic.List`1[T].get_Item (System.Int32 index) [0x00009] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/List.cs:161 
  at System.Collections.Generic.List`1[T].System.Collections.IList.get_Item (System.Int32 index) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/List.cs:188 
  at redacted.Data.ViewModels.RefreshableBaseCollectionViewModel`2[TModel,TViewModel].get_Item (System.Int32 index) [0x00000] in /Users/dpfeiffer/repos/redacted.app2/redacted.Data/View Models/RefreshableBaseCollectionViewModel.cs:74 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.ElementAt (System.Int32 index) [0x0000f] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:240 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.get_Item (System.Int32 index) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:40 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.get_Item (Foundation.NSIndexPath indexPath) [0x00019] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:96 
  at Xamarin.Forms.Platform.iOS.ItemsViewController`1[TItemsView].UpdateTemplatedCell (Xamarin.Forms.Platform.iOS.TemplatedCell cell, Foundation.NSIndexPath indexPath) [0x00024] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ItemsViewController.cs:250 
  at Xamarin.Forms.Platform.iOS.ItemsViewController`1[TItemsView].CreateMeasurementCell (Foundation.NSIndexPath indexPath) [0x0007b] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ItemsViewController.cs:587 
  at Xamarin.Forms.Platform.iOS.ItemsViewController`1[TItemsView].GetPrototype () [0x0005d] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ItemsViewController.cs:362 
  at Xamarin.Forms.Platform.iOS.ItemsViewLayout.DetermineCellSize () [0x00060] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ItemsViewLayout.cs:211 
  at Xamarin.Forms.Platform.iOS.ListViewLayout.ConstrainTo (CoreGraphics.CGSize size) [0x0001e] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ListViewLayout.cs:16 
  at Xamarin.Forms.Platform.iOS.ItemsViewController`1[TItemsView].CheckForEmptySource () [0x0005d] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ItemsViewController.cs:125 
  at Xamarin.Forms.Platform.iOS.ItemsViewController`1[TItemsView].NumberOfSections (UIKit.UICollectionView collectionView) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ItemsViewController.cs:231 
  at (wrapper managed-to-native) ObjCRuntime.Messaging.nint_objc_msgSend_nint(intptr,intptr,System.nint)
  at UIKit.UICollectionView.NumberOfItemsInSection (System.nint section) [0x0000d] in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/ios/native/UIKit/UICollectionView.g.cs:552 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.CollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs args) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:115 
  at Xamarin.Forms.Platform.iOS.ObservableItemsSource.CollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args) [0x0002d] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ObservableItemsSource.cs:108 
  at (wrapper delegate-invoke) <Module>.invoke_void_object_NotifyCollectionChangedEventArgs(object,System.Collections.Specialized.NotifyCollectionChangedEventArgs)
  at Float.Core.ViewModels.BaseCollectionViewModel`2[TModel,TViewModel].<OnElementsChanged>b__28_0 () [0x0000b] in /Users/jenkins/.jenkins/jobs/Float-NuGet-Core/workspace/Float.Core/ViewModels/BaseCollectionViewModel.cs:275 
  at Foundation.NSAsyncActionDispatcher.Apply () [0x00000] in /Users/builder/azdo/_work/1/s/xamarin-macios/src/Foundation/NSAction.cs:152 
--- End of stack trace from previous location where exception was thrown ---

  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Users/builder/azdo/_work/1/s/xamarin-macios/src/UIKit/UIApplication.cs:86 
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0000e] in /Users/builder/azdo/_work/1/s/xamarin-macios/src/UIKit/UIApplication.cs:65 
  at redacted.iOS.Application.Main (System.String[] args) [0x00000] in /Users/dpfeiffer/repos/redacted.app2/redacted.iOS/Main.cs:33

This exception was specifically generated by starting with an observable collection, adding one item, and then removing that one item. You'll notice from the stack trace that despite there being no elements in the collection, XF attempts to create the first cell to measure for layout purposes (because it doesn't realize the list is now empty).

Basic Information

  • Version with issue: 5.0.0.1874
  • Last known good version: 4.8.0.1821
  • Platform Target Frameworks:
    • iOS: 14.3
    • Android: N/A
    • UWP: N/A
  • Android Support Library / AndroidX Version: N/A
  • NuGet Packages: N/A
  • Affected Devices: N/A

Environment

Show/Hide Visual Studio info
=== Visual Studio Enterprise 2019 for Mac ===

Version 8.9.6 (build 6)
Installation UUID: 396335d3-ed5f-4c3b-8739-b2428955e66e
	GTK+ 2.24.23 (Raleigh theme)
	Xamarin.Mac 6.18.0.23 (d16-6 / 088c73638)

	Package version: 612000125

=== Mono Framework MDK ===

Runtime:
	Mono 6.12.0.125 (2020-02/8c552e98bd6) (64-bit)
	Package version: 612000125

=== Roslyn (Language Service) ===

3.9.0-6.21152.10+c10f884b30737542ddd84ca889a4aad9281ce210

=== NuGet ===

Version: 5.8.0.6860

=== .NET Core SDK ===

SDK: /usr/local/share/dotnet/sdk/5.0.202/Sdks
SDK Versions:
	5.0.202
	5.0.201
	5.0.103
	5.0.102
	5.0.101
	5.0.100
	3.1.408
	3.1.407
	3.1.406
	3.1.405
	3.1.404
	3.1.402
	3.1.401
	3.1.302
	3.1.301
	3.1.300
	3.1.200
	3.1.101
	3.1.100
	3.0.101
	3.0.100
	2.1.701
	2.1.505
	2.1.504
	2.1.503
	2.1.302
	2.1.301
	2.1.4
	2.0.0
	1.0.3
MSBuild SDKs: /Applications/Visual Studio.app/Contents/Resources/lib/monodevelop/bin/MSBuild/Current/bin/Sdks

=== .NET Core Runtime ===

Runtime: /usr/local/share/dotnet/dotnet
Runtime Versions:
	5.0.5
	5.0.4
	5.0.3
	5.0.2
	5.0.1
	5.0.0
	3.1.14
	3.1.13
	3.1.12
	3.1.11
	3.1.10
	3.1.8
	3.1.7
	3.1.6
	3.1.5
	3.1.4
	3.1.2
	3.1.1
	3.1.0
	3.0.1
	3.0.0
	2.1.23
	2.1.22
	2.1.21
	2.1.20
	2.1.19
	2.1.18
	2.1.16
	2.1.15
	2.1.14
	2.1.13
	2.1.12
	2.1.9
	2.1.8
	2.1.7
	2.1.2
	2.1.1
	2.0.5
	2.0.0
	1.1.1
	1.0.4

=== .NET Core 3.1 SDK ===

SDK: 3.1.408

=== Xamarin.Profiler ===

Version: 1.6.13.11
Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

=== Updater ===

Version: 11

=== Apple Developer Tools ===

Xcode 12.4 (17801)
Build 12D4e

=== Xamarin.Mac ===

Version: 7.8.2.5 (Visual Studio Enterprise)
Hash: 3836759d4
Branch: d16-9
Build date: 2021-02-10 17:56:43-0500

=== Xamarin.Android ===

Version: 11.2.2.1 (Visual Studio Enterprise)
Commit: xamarin-android/d16-9/877f572
Android SDK: /Users/dpfeiffer/Library/Android/sdk
	Supported Android versions:
		4.4 (API level 19)
		5.0 (API level 21)
		5.1 (API level 22)
		6.0 (API level 23)
		7.0 (API level 24)
		7.1 (API level 25)
		8.1 (API level 27)

SDK Tools Version: 26.1.1
SDK Platform Tools Version: 29.0.2
SDK Build Tools Version: 29.0.2

Build Information: 
Mono: 5e9cb6d
Java.Interop: xamarin/java.interop/d16-9@54f8c24
ProGuard: Guardsquare/proguard/v7.0.1@912d149
SQLite: xamarin/sqlite/3.34.1@daff8f4
Xamarin.Android Tools: xamarin/xamarin-android-tools/d16-9@d210f11

=== Microsoft OpenJDK for Mobile ===

Java SDK: /Users/dpfeiffer/Library/Developer/Xamarin/jdk/microsoft_dist_openjdk_1.8.0.25
1.8.0-25
Android Designer EPL code available here:
https://github.com/xamarin/AndroidDesigner.EPL

=== Android SDK Manager ===

Version: 16.9.0.22
Hash: a391de2
Branch: remotes/origin/d16-9~2
Build date: 2021-03-24 08:30:26 UTC

=== Android Device Manager ===

Version: 16.9.0.17
Hash: fc2b3db
Branch: remotes/origin/dev/jmt/d16-9bump~1
Build date: 2021-03-24 08:30:44 UTC

=== Xamarin.iOS ===

Version: 14.14.2.5 (Visual Studio Enterprise)
Hash: 3836759d4
Branch: d16-9
Build date: 2021-02-10 17:56:44-0500

=== Xamarin Designer ===

Version: 16.9.0.323
Hash: 1b4790c08
Branch: remotes/origin/d16-9
Build date: 2021-03-31 05:12:20 UTC

=== Build Information ===

Release ID: 809060006
Git revision: 47cf16e38721a785b8e2296ce6716502f34261ac
Build date: 2021-04-07 07:23:18-04
Build branch: release-8.9
Xamarin extensions: 47cf16e38721a785b8e2296ce6716502f34261ac

=== Operating System ===

Mac OS X 10.15.7
Darwin 19.6.0 Darwin Kernel Version 19.6.0
    Tue Jan 12 22:13:05 PST 2021
    root:xnu-6153.141.16~1/RELEASE_X86_64 x86_64

=== Enabled user installed extensions ===

XAML Styler 2.0.1


Build Logs

Screenshots

image

Reproduction Link

N/A

Workaround

None.

@mediabounds mediabounds added s/unverified New report that has yet to be verified t/bug 🐛 labels Apr 16, 2021
@mediabounds
Copy link
Author

This might be related to the issue in #9632 -- but I opened a separate issue since the stack trace was different.

@nschoenberg
Copy link

I think I managed to workaround this issue by setting IsVisible of collection view to false as soon as I know there are no items to display. XF 5.0

@jaymelbe
Copy link

Any news about this issue? Facing that one... tried to downgrade to 4.8.0.1821 but I can't because of other issues (with RadioButton being experimental).
Tried everything.. removing the collection, hiding the component,. Nothing has worked. Is there any fix coming?

@MAVREE
Copy link

MAVREE commented Dec 14, 2021

I just encountered this same bug, I get ArgumentOutOfRangeExceptions out of simple .Clear() operations, XF 5.0.0.2291

@hartez hartez removed their assignment Jul 28, 2022
jtorvald added a commit to jtorvald/Xamarin.Forms that referenced this issue Jan 5, 2023
@LeoJHarris
Copy link

LeoJHarris commented Oct 4, 2023

I just encountered this same bug, I get ArgumentOutOfRangeExceptions out of simple .Clear() operations, XF 5.0.0.2291

@MAVREE Same issue here .Clear() seems less then reliable, I have swapped many of instances of .Clear() to .ReplaceRange() instead

@MitchBomcanhao
Copy link

MitchBomcanhao commented Oct 4, 2023

I've replaced uses of the clear method with a different one where, depending on the number of items, it'll clear the collection (if more than 1 item is present) or replace the collection with a new one (if there is only 1 item in the collection). note that replacing the collection with a new one will break binding so you need to have something in place to notify the UI that the items source property has been changed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

8 participants