0

I am very stumped with this issue. Basically on iOS my CollectionView will not work - it throws the following error:

Invalid update: invalid number of sections. The number of sections contained in the collection view after the update (2) must be equal to the number of sections contained in the collection view before the update (2), plus or minus the number of sections inserted or deleted (1 inserted, 0 deleted)

I have tried a few existing fixes from StackOverflow with the same error but none of them seem to fit. Here is the code whereby the changes are made to the ObservableCollection:

async Task DisplayMessage(object sender, CustomEventArgs e)
        {

            Message message = e.MessageSnapshot;

            Console.WriteLine("Message Content: " + e.MessageSnapshot.Content);

            if (message.TimeStamp.Date != lastMessageTime.Date)
            {
                lastMessageGroup = new MessageGroup
                {
                    Name = message.TimeStamp.ToString("dd MMM")
                };
            }
            else
            {
                MessagesList.Remove(lastMessageGroup);
            }

            lastMessageTime = message.TimeStamp;
            Console.WriteLine("Arrived here at least once!");
            lastMessageGroup.Add(message);
            MessagesList.Add(lastMessageGroup);
            Console.WriteLine("Completed at least once!");

        }

This snippet is part of a messaging system and so is run by an event firing as a result of a change in the database. It works once the rest of the items have been displayed (at displaying the items one at a time) but initially on page load when the event fires multiple times to populate the view with the existing conversation, the view freezes and you receive this error. Sometimes it will completely crash, sometimes it will throw the error and leave the view empty.

So far I have tried:

  • Adding lock() statement around the .Remove() and .Add() lines to ensure these lines within each event fire are not being run at the same time
  • Adding await Task.Delay(1000); after the .Remove() line and at the bottom of the function

Any help will be greatly appreciated!

Matthew Swallow
  • 179
  • 1
  • 11
  • The message happens when ios updates collectionview based on the collection you are changing. That ios code runs on main thread. If your code is on a different thread, it can alter collection at a bad time. Wrap your code in call to MainThread.BeginInvokeOnMainThread. Or any similar function that ensures your code is on main thread. This limitation of xamarin forms on ios does not appear to be documented. – ToolmakerSteve Mar 05 '23 at 18:17
  • @ToolmakerSteve Do I need to wrap this function or the place where the event is invoked? Many thanks! – Matthew Swallow Mar 05 '23 at 19:29
  • 1
    Whenever you update your CollectionView's ItemSource, do it on MainThread – FreakyAli Mar 06 '23 at 02:13
  • Matthew, looks like simplest fix is to wrap the entire contents of `DisplayMessage`, starting with `Message message =`. In other situations, you might wrap the call to a method. Either way, the goal is to make sure when lines like `MessagesList.Remove` or `MessagesList.Add` are executed, code is on MainThread. For testing, use `MainThread.IsOnMainThread` bool to verify. – ToolmakerSteve Mar 06 '23 at 18:52

1 Answers1

2

This is a known problem of xamarin in ios. Someone mentioned the bug on github: [Bug] [iOS] CollectionView iOS inner crash while adding items to group, items aren't displayed #13268, you can continue to follow this issue.

Zack
  • 1,255
  • 1
  • 2
  • 5