Xamarin iOS app crashes when changing from Landscape orientation to Portrait orientation

Viewed 147

TLDR Xamarin.Forms 5.0.0.2401 app crashes when going from Landscape orientation to view with collectionview that is in Portrait orientation.

Context

Hi, i have a Xamarin.Forms 5.0.0.2401 that has a default setting in the AppDelegate.cs that the app should always in Portrait orientation with the only exception from one view that is stated in the override method GetSupportedInterfaceOrientations.

Code from AppDelegate:

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, [Transient] UIWindow forWindow)
{
   if (Shell.Current.Navigation.ModalStack.LastOrDefault() is CardPage)
   {
      return UIInterfaceOrientationMask.Landscape;
   }

   return UIInterfaceOrientationMask.Portrait;
}

But when i navigate out from the landscape view to a view with a collectionview that is previous filled with items due to scrolling the app crashes.

I navigate via using following code:

Code inside viewmodel for CardPage that is being forced to lanscape orientation by code in AppDelegate.cs

async Task ExecuteCloseCommand() => await GoToAsync("..", true);

Code from BaseViewModel (that CardPage inheirts from) to handle navigation in the stack.

protected Task GoToAsync(string uri, bool animate = false)
            => MainThread.InvokeOnMainThreadAsync(async () => await Shell.Current.GoToAsync(uri, animate));

Error message on crash

But the exception i get from the crash is following:

>{System.NullReferenceException: Object reference not set to an instance of an object
at Xamarin.Forms.Platform.iOS.ItemsViewController`1[TItemsView].CheckForEmptySource () [0x00028]  
 in D:\a\_work\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ItemsViewController.cs:117   
at Xamarin.Forms.Platform.iOS.ItemsViewController`1[TItemsView].NumberOfSections  
 (UIKit.UICollectionView collectionView) [0x00000]  
 in D:\a\_work\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ItemsViewController.cs:256  
at (wrapper managed-to-native) ObjCRuntime.Messaging.void_objc_msgSendSuper(intptr,intptr)  
at UIKit.UICollectionViewLayout.PrepareLayout () [0x00023]  
 in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/ios/native/UIKit/UICollectionViewLayout.g.cs:496  
at Xamarin.Forms.Platform.iOS.ItemsViewLayout.PrepareLayout () [0x00000]  
 in D:\a\_work\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ItemsViewLayout.cs:415   
at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)  
at UIKit.UIApplication.Main (System.String[] args,  
 System.Type principalClass, System.Type delegateClass) [0x0003b]  
 in /Users/builder/azdo/_work/1/s/xamarin-macios/src/UIKit/UIApplication.cs:85  
at <ProjectName>.iOS.Application.Main (System.String[] args) [0x00001]  
 in C:\Users\JesperEngdahl\source\repos\<ProjectName>\Main.cs:17 }

So i suspect that there is something in Xamarin.Forms.Platform.iOS that is making the crash specifically the ItemsViewController on line 117. That it is somehow making a assumption that the collectionview is empty, but its not and then it craches.

I am kinda stumped and not really sure how to handle this kind of crash, please help.

1 Answers

Perhaps can re-initialize the CollectionView, when returning to that page.

As a test, does this help (or at least change the symptom):

<ContentPage ...>
    ...
    <CollectionView x:Name="theCollectionView" ... >
        ...
        private bool secondTime;

        protected override void OnAppearing()
        {
            base.OnAppearing();

            if (secondTime)
            {
                // TEST: Try to force collection view to release its items.
                var holdItems = theCollectionView.ItemsSource;
                // change "string" as needed. Set to an empty collection of the type of your ItemsSource.
                theCollectionView.ItemsSource = new List<string>();

                Device.BeginInvokeOnMainThread(async () =>
                {
                    // TEST: Long delay, to make sure page has appeared with an empty collection.
                    await Task.Delay(1000);
                    theCollectionView.ItemsSource = holdItems;
                });

            }
            else
            {
                secondTime = true;
            }
        }

If this helps avoid the exception, then can explore how to do this without the long delay.

Related