using System;
+using System.Collections.Generic;
using Foundation;
using UIKit;
readonly ItemsView _itemsView;
ItemsViewLayout _layout;
bool _initialConstraintsSet;
+ bool _safeForReload;
bool _wasEmpty;
bool _currentBackgroundIsEmptyView;
{
_itemsView = itemsView;
_itemsSource = ItemsSourceFactory.Create(_itemsView.ItemsSource, CollectionView);
+
+ // If we already have data, the UICollectionView will have items and we'll be safe to call
+ // ReloadData if the ItemsSource changes in the future (see UpdateItemsSource for more).
+ _safeForReload = _itemsSource?.Count > 0;
UpdateLayout(layout);
}
public virtual void UpdateItemsSource()
{
- _itemsSource = ItemsSourceFactory.Create(_itemsView.ItemsSource, CollectionView);
+ if (_safeForReload)
+ {
+ UpdateItemsSourceAndReload();
+ }
+ else
+ {
+ // Okay, thus far this UICollectionView has never had any items in it. At this point, if
+ // we set the ItemsSource and try to call ReloadData(), it'll crash. AFAICT this is a bug, but
+ // until it's fixed (or we can figure out another way to go from empty -> having items), we'll
+ // have to use this crazy workaround
+ EmptyCollectionViewReloadWorkaround();
+ }
+ }
+
+ void UpdateItemsSourceAndReload()
+ {
+ _itemsSource = ItemsSourceFactory.Create(_itemsView.ItemsSource, CollectionView);
CollectionView.ReloadData();
CollectionView.CollectionViewLayout.InvalidateLayout();
}
+ void EmptyCollectionViewReloadWorkaround()
+ {
+ var enumerator = _itemsView.ItemsSource.GetEnumerator();
+
+ if (!enumerator.MoveNext())
+ {
+ // The source we're updating to is empty, so we can just update as normal; it won't crash
+ UpdateItemsSourceAndReload();
+ }
+ else
+ {
+ // Grab the first item from the new ItemsSource and create a usable source for the UICollectionView
+ // from that
+ var firstItem = new List<object> { enumerator.Current };
+ _itemsSource = ItemsSourceFactory.Create(firstItem, CollectionView);
+
+ // Insert that item into the UICollectionView
+ // TODO ezhart When we implement grouping, this will need to be the index of the first actual item
+ // Which might not be zero,zero if we have empty groups
+ var indexesToInsert = new NSIndexPath[1] { NSIndexPath.Create(0, 0) };
+
+ UIView.PerformWithoutAnimation(() =>
+ {
+ CollectionView.InsertItems(indexesToInsert);
+ });
+
+ // Okay, from now on we can just call ReloadData and things will work fine
+ _safeForReload = true;
+ UpdateItemsSource();
+ }
+ }
+
protected virtual void UpdateDefaultCell(DefaultCell cell, NSIndexPath indexPath)
{
cell.Label.Text = _itemsSource[indexPath.Row].ToString();