Xamarin.Forms
Xamarin.Forms copied to clipboard
[Bug] [iOS] CollectionView iOS inner crash while adding items to group, items aren't displayed
Description
I was testing the latest build of XamarinForms when I realized that there is an issue related to a group's item manipulation on the iOS platform. I can't reproduce this error on the Android platform.
I've also tried to use ObservableRangeCollection
without any noticeable difference from the default ObservableCollection
.
There are also a few lines of iOS inner exception message:
2021-01-02 14:32:21.361034+0200 xf_cv_range.iOS[3615:42647] *** Assertion failure in -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:collectionViewAnimator:], UICollectionView.m:7294
[0:] Foundation.MonoTouchException: Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: Invalid update: invalid number of sections. The number of sections contained in the collection view after the update (1) must be equal to the number of sections contained in the collection view before the update (1), plus or minus the number of sections inserted or deleted (1 inserted, 0 deleted).
Full output log is here 02_01_2021__14_40_13__e09b3d8b-4a6c-4d31-b7c0-9f047d3c1dfa.txt
I will add any additional info if needed.
Steps to Reproduce
- Use Xamarin.Forms 4.8.0.1821
- Add empty group to the ObservableCollection, then add items to the group:
var group = new Group();
Items.Add(group);
foreach (var item in items)
group.Add(item);
- Run the app.
If you are using my demo project:
- Run the app on any iOS device/simulator.
- Switch to the second tab (Browse)
- Apply pull-to-refresh on the CV.
- You can downgrade XF version to 4.8.0.1687 and repeat the test to see that now it's working.
Expected Behavior
Added items are presented (visible) on the screen.
Actual Behavior
Added items aren't presented (visible) on the screen. You can see the exception in the VS's output window.
Basic Information
- Version with issue: Xamarin.Forms 4.8.0.1821 (latest for today)
- Last known good version: Xamarin.Forms 4.8.0.1687
- Platform Target Frameworks:
- iOS: 14.2
- Android: No issue on this platform
Environment
not applicable
Build Logs
not applicable
Screenshots
Good result (XF 4.8.0.1687): https://user-images.githubusercontent.com/3184414/103457346-2ec98280-4d07-11eb-81e1-caabdf11bce0.mp4 Bad result (XF 4.8.0.1821): https://user-images.githubusercontent.com/3184414/103457371-6df7d380-4d07-11eb-8916-0615bedaae21.mp4
Reproduction Link
https://github.com/bondarenkod/xf_cv_group_add_range_bug
Workaround
Downgrade to Xamarin.Forms 4.8.0.1687
This is happening in Xamarin Forms 5.0.0.1829-pre6 as well. Code was previously working on older versions of Xamarin <= 4.8.0.1687.
This is only triggered with IsGrouped="True"
Bind your list after the for statement. If you add itens to your list as you bind it to your collectionView the app is going to crash
I think issue with ObservableCollection. Generic List works on iOS on XF>4.8.0.1687, but it doesn't bind CollectionView IsGrouped on Android. ObservableCollection is important part of MVVM, it should be fixed. Downgraded XF 4.8.1687 for working on both platforms for now.
@kgouraw nope, the problem inside the synchronizer.
Are there any updates on this? I know it's only been reported recently but it really slows down our dev/test cycles.
In version 5.0.0.2012 no changes, we are waiting
I was actually able to work around this issue by using the ObservableRangeCollection and using it's AddRange() method. It might have been a different underlying issue though.
I was actually able to work around this issue by using the ObservableRangeCollection and using it's AddRange() method. It might have been a different underlying issue though.
Let's try by AddRange. I will write how the results will be.
I was actually able to work around this issue by using the ObservableRangeCollection and using it's AddRange() method. It might have been a different underlying issue though.
The result is negative. Did not help. Let's try to think of another solution.
@RenatGaliew try to use dynamic data
@bondarenkod my data is already dynamic, once the data is loaded everything is fine, then after switching to another page and returning to the current one, an error crashes and nothing more will be added, it crashes on the add method
I am seeing the same thing, and I am also using the Dynamic Data package to operate the collection.
@RenatGaliew oh, sorry, I meant this https://github.com/reactivemarbles/DynamicData
Any working workaround?
Still Crashing !! Xamarin Forms : 5.0.0.2012
This happens when grouped items are added to an ObservableCollection that is bound to a CollectionView. It works fine up to XF 4.8.0.1687. Any version since then generates the error in the original post. As a workaround, I don't bind the CollectionView in xaml. My CollectionView is inside a RefreshView, so I use code behind PropertyChanged event "IsRefreshing". If true then RemoveBinding. If false then SetBinding. Basically removing the binding before populating the collection, then adding the binding once the collection is fully populated. In the ViewModel, don't reuse the ObservableCollection with the .Clear method. Always instantiate the variable as a new ObservableCollection. I battled this for days, and this was the only way I could avoid the error.
await Task.Delay(300);
//Then again bind the cleaned Observable collection object.
This trick just worked for me.
I worked around the issue by adding a private method to do the updating where the binding is removed/added. Everywhere in the code where I previously updated my ObservableCollection I now instead call the new private method using a new ObservableCollection each time.
before:
MeetingLocationsGrouped.Clear();
MeetingLocationsGrouped = new ObservableCollection<Grouping<DayOfWeek, MeetingLocationPageModel>>(result);
after:
UpdateMeetingLocationsGrouped(new ObservableCollection<Grouping<DayOfWeek, MeetingLocationPageModel>>());
UpdateMeetingLocationsGrouped(new ObservableCollection<Grouping<DayOfWeek, MeetingLocationPageModel>>(result));
private void UpdateMeetingLocationsGrouped(ObservableCollection<Grouping<DayOfWeek, MeetingLocationPageModel>> data)
{
_meetingLocationsCollectionView.RemoveBinding(CollectionView.ItemsSourceProperty);
MeetingLocationsGrouped = data;
_meetingLocationsCollectionView.SetBinding(CollectionView.ItemsSourceProperty, nameof(this.MeetingLocationsGrouped));
}
I've just tested this bug again, this time directly in XF sources, it seems like the issue is still there and 100% reproducible.
For those who are stuck with it, it can be fixed by adding a small delay between .Clear()
and .Add()
.
In my demo adding even await Task.Delay(100);
eliminated the crash.
var itemsToAdd = Enumerable.Range(0, 20).Select(x => new Member($"Guardian-{x}")).ToArray();
var group = new ObservableTeam("Excalibur", new List<Member>(0));
itemsSource.Clear();
await Task.Delay(100);
itemsSource.Add(group);
foreach (var item in itemsToAdd)
group.Add(item);
https://user-images.githubusercontent.com/3184414/121402297-5f6eb180-c962-11eb-88de-800b1dccd450.mp4
Adding .LayoutIfNeeded()
into L:\src_github\xf500\Xamarin.Forms.Platform.iOS\CollectionView\ObservableGroupedSource.cs
eliminated the crash.
void Reload()
{
ResetGroupTracking();
_collectionView.ReloadData();
_collectionView.LayoutIfNeeded();
_collectionView.CollectionViewLayout.InvalidateLayout();
}
But it continues writing such messages to the console (the same in the attached demo, so I'll skip it for now):
2021-06-09 23:47:34.850570+0300 XamarinFormsControlGalleryiOS[33463:330322] [UICollectionView] Invalid update:
invalid number of items in section 0.
The number of items contained in an existing section after the update (1)
must be equal to the number of items contained in that section before the update (1),
plus or minus the number of items inserted or deleted from that section (1 inserted, 0 deleted)
and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out). -
will perform reloadData. UICollectionView instance: <UICollectionView: 0x7ffaa5057800;
frame = (0 0; 390 753); clipsToBounds = YES; autoresize = W+H; gestureRecognizers =
<NSArray: 0x600001cb48d0>; layer = <CALayer: 0x6000016ef8a0>; contentOffset: {0, 0}; contentSize: {390, 65}; adjustedContentInset: {0, 0, 0, 0}; layout: <Xamarin_Forms_Platform_iOS_ListViewLayout:
0x7ffaa601cc80>; dataSource: <Xamarin_Forms_Platform_iOS_GroupableItemsViewController_1:
0x7ffaa601d4f0>>; currentUpdate: [UICollectionViewUpdate - 0
x7ffaa3d6a890: old:<UICollectionViewData: 0x600002dc1fe0>
new<UICollectionViewData: 0x600002df83c0> items:<(
"I(0,0)"
)>]
I've opened up a similar issue for this, when the CollectionView is Grouped and I try to .Add() multiple items. Very frustrating. https://github.com/xamarin/Xamarin.Forms/issues/14362
Adding “await Task.Delay(100);”, or even 1ms helps, but does introduce a strange behavior when users scrolls the list. It seems to flick and get very slow - almost unusable, in my case. Another issue is the pull to refresh. It stopped working.
Going back to old version of XF. Thanks for help.
Seems like some people reported this as still not working unfortunately.
Everyone still experiencing this and watching this issue, a PR for this is open now, would you be able to grab the NuGet as described here and let us know if this fixes this issue? That will greatly speed up the review process. Make sure to take the exact version number that is listed on the PR.
Besides verifying if this particular issue is fixed also be sure to check other scenarios in the same area to make sure that this fix doesn't accidentally has side-effects 🙂
Thanks!
Anyone able to test this?
@jfversluis I've been working with a customer who is still seeing this issue. They have helped create a repro sample app which consistently crashes ReproSample
I'm sorry guys, I'm currently closing release, so I'm not able to pay any attention to this issue nor this or the next week.
Anyone able to test this?
@jfversluis I have tested the PR. My problems with the CollectionView were solved with it!
@jfversluis ?? Where to find the NuGet? Nothing in the DevOps artifact. Sorry. I am newbie, may be making a stupid mistake.
@jfversluis ?? Where to find the NuGet? Nothing in the DevOps artifact. Sorry. I am newbie, may be making a stupid mistake.
You have to add an additional package source (https://aka.ms/forms-prs/index.json), then the NuGet will be found.