-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[Catalyst] Fix: CollectionView Crash #29801
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,12 +25,22 @@ protected override UICollectionViewDelegateFlowLayout CreateDelegator() | |
| // _Only_ called if the user initiates the selection change; will not be called for programmatic selection | ||
| public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath) | ||
| { | ||
| if (indexPath is null || indexPath.Handle == IntPtr.Zero) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| FormsSelectItem(indexPath); | ||
| } | ||
|
|
||
| // _Only_ called if the user initiates the selection change; will not be called for programmatic selection | ||
| public override void ItemDeselected(UICollectionView collectionView, NSIndexPath indexPath) | ||
| { | ||
| if (indexPath is null || indexPath.Handle == IntPtr.Zero) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| FormsDeselectItem(indexPath); | ||
| } | ||
|
|
||
|
|
@@ -39,6 +49,11 @@ internal void SelectItem(object selectedItem) | |
| { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To extend on @PureWeen’s comment here: #29801 (comment) Something like this might help avoid re-selecting stale or unintended items if the ItemsSource has changed between scheduling and executing the batch update: internal void SelectItem(object selectedItem)
{
var originalSource = ItemsView.ItemsSource;
var index = GetIndexForItem(selectedItem);
if (index.Section > -1 && index.Item > -1)
{
// Ensure the selected index is updated after the collection view's items generation is completed
CollectionView.PerformBatchUpdates(null, _ =>
{
// Exit if the ItemsSource reference no longer matches the one captured at invocation.
if (!ReferenceEquals(ItemsView.ItemsSource, originalSource))
{
return;
}
// Recalculate the index for the selectedItem now that the collection may have changed.(Adding, deleting etc..)
var updatedIndex = GetIndexForItem(selectedItem);
if (updatedIndex.Section < 0 || updatedIndex.Item < 0)
{
return;
}
// Retrieve the current item at that index and verify it still equals the intended selection.
var liveItem = GetItemAtIndex(updatedIndex);
if (!Equals(liveItem, selectedItem))
{
return;
}
CollectionView.SelectItem(index, true, UICollectionViewScrollPosition.None);
CollectionView.CellForItem(index)?.UpdateSelectedAccessibility(true);
});
}
} |
||
| var index = GetIndexForItem(selectedItem); | ||
|
|
||
| if (index is null || index.Handle == IntPtr.Zero) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| if (index.Section > -1 && index.Item > -1) | ||
| { | ||
| // Ensure the selected index is updated after the collection view's items generation is completed | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -25,12 +25,22 @@ protected override UICollectionViewDelegateFlowLayout CreateDelegator() | |||||
| // _Only_ called if the user initiates the selection change; will not be called for programmatic selection | ||||||
| public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath) | ||||||
| { | ||||||
| if (indexPath is null || indexPath.Handle == IntPtr.Zero) | ||||||
|
||||||
| if (indexPath is null || indexPath.Handle == IntPtr.Zero) | |
| if (!IsValidIndexPath(indexPath)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar guard logic is repeated here—extract into a shared helper method to keep the code DRY and make future updates simpler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion IsValidIndexPath can be used for this check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think IsValidIndexPath is only on ListViewRenderer?
One thing I'm wondering is if we should re-evalute the indexes when they are used inside of PerformBatchUpdates
like in this code
if the index should be retrieved a second time and if it's changed at all then we don't process the update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@PureWeen The case you mentioned could occur if the ItemsSource is updated immediately after setting the SelectedItem property, as shown in the example below. In such scenarios, during the PerformBatchUpdates call, the CollectionView items may be modified, and the index might no longer exist in the collection. In this case, we do not proceed with updating the collection.
However, the originally reported issue is unrelated to that scenario. As seen in the stack trace, the issue originates from the ItemSelected override method, which is triggered when the user taps to select an item. This indicates that the crash is likely occurring during user interaction. On the other hand, the SelectItem method you referenced is only invoked during programmatic selection, which is not the case here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sheiksyedm, will the changes in this PR also fix the issue caused by the 'ItemsSource updated immediately' problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bhavanesh2001 No, it will not fix the ItemsSource updated problem. This fix may only address the ObjectDisposedException observed in the reported stack trace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/dotnet/maui/pull/29801/files#r2125125141
I'm wondering if we should re-evaluate the index when the performbatchupdate method is called and if that's the better overall fix here?
Or maybe we should change the ordering?
CollectionView.SelectItem(index, true, UICollectionViewScrollPosition.None);
Is going to trigger a behavior change reaction in the code
Would it make sense to have it like this instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have this one https://github.com/dotnet/maui/blob/main/src/Compatibility/Core/src/iOS/CollectionView/IndexPathHelpers.cs#L36
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well thats Compatibility , this is the one I think we use on the CV
maui/src/Controls/src/Core/Handlers/Items/iOS/IndexPathHelpers.cs
Line 37 in 9894e0f