Skip to content
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

[iOS] NullReferenceException from FlexLayout.InitItemProperties #21711

Closed
Larhei opened this issue Apr 8, 2024 · 10 comments
Closed

[iOS] NullReferenceException from FlexLayout.InitItemProperties #21711

Larhei opened this issue Apr 8, 2024 · 10 comments
Labels
area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter fixed-in-8.0.21 fixed-in-9.0.0-preview.4.10690 i/regression This issue described a confirmed regression on a currently supported version layout-flex FlexLayout issues platform/iOS 🍎 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Milestone

Comments

@Larhei
Copy link

Larhei commented Apr 8, 2024

Description

After upgrading to the new maui version we are seeing a crash on iOS in on of our views.

The Callstack is

   at Microsoft.Maui.Controls.FlexLayout.InitItemProperties(IView view, Item item)
   at Microsoft.Maui.Controls.FlexLayout.EnsureFlexItemPropertiesUpdated()
   at Microsoft.Maui.Controls.FlexLayout.Layout(Double width, Double height)
   .......

(see relevant log output for complete stack trace)

In our ViewModel we are adding items to an Observable Collection in a foreach loop with some delay.
This ObservableCollection is bound to a CollectionView.

<DataTemplate x:Key="TagsTemplate" x:DataType="local:Tags">
    <ContentView>
        <VerticalStackLayout Margin="24,0">
           <Label Text="{x:Binding Header, Mode=OneTime}" TextColor="{StaticResource Primary}"/>
            <FlexLayout BindableLayout.ItemsSource="{x:Binding Modes, Mode=OneTime}" Wrap="Wrap" Direction="Row" JustifyContent="Start">
                <BindableLayout.ItemTemplate>
                    <DataTemplate x:DataType="system:String">
                         <Label Text="{x:Binding Mode=OneTime}" Background="{StaticResource Neutral0}" TextType="Html"/>
                    </DataTemplate>
                </BindableLayout.ItemTemplate>
            </FlexLayout>
        </VerticalStackLayout>
    </ContentView>
</DataTemplate>

Before Maui Version 8.0.14 this exception only happened when the Cell was not initial in the viewport and when scrolling it into view. So we changed our layout logic to have this cells in the viewport to not facing the issue. But now also views in the initial viewport are getting this null pointer. From my debugging it looks to me that even when setting Binding to OneTime the BindableLayout.ItemsSource is behaving interesting.
When Subclassing Flexlayout the OnAddItem for each item in the Modes Collection is called. This is expected.
Then there comes Layout. This is expected also.
But than there comes a OnClear call for unknown reason... than OnAddItem for first item in Modes Collection... and than Layout again. And this is not expected. I did not change the Mode Collection in the ItemsSource. My ItemsSource contains more than one item. So why it only want to layout that single item... unknown.

The NullPointer is caused by
GetFlexItem(BindableObject bindable) returning null

This can only happen if AddFlexItem is called when _root is null. And this is the case I guess because the call to OnClear sets _root to null.

But this just my2cents.

Steps to Reproduce

  1. Checkout the repro
  2. Start the Project on iOS Emulator or Device
  3. Wait 2 Seconds till crash is happening.

Link to public reproduction project repository

https://github.com/Larhei/Maui-Issues/tree/main/FlexLayout

Version with bug

8.0.14 SR3.1

Is this a regression from previous behavior?

Yes, this used to work in .NET MAUI

Last version that worked well

8.0.7 SR2

Affected platforms

iOS

Affected platform versions

No response

Did you find any workaround?

Remove TextType="Html" from the Label. But I really need HTML text here.

Relevant log output

at Microsoft.Maui.Controls.FlexLayout.InitItemProperties(IView view, Item item)
   at Microsoft.Maui.Controls.FlexLayout.EnsureFlexItemPropertiesUpdated()
   at Microsoft.Maui.Controls.FlexLayout.Layout(Double width, Double height)
   at Microsoft.Maui.Layouts.FlexLayoutManager.Measure(Double widthConstraint, Double heightConstraint)
   at Microsoft.Maui.Controls.FlexLayout.CrossPlatformMeasure(Double widthConstraint, Double heightConstraint)
   at Microsoft.Maui.Platform.MauiView.CrossPlatformMeasure(Double widthConstraint, Double heightConstraint)
   at Microsoft.Maui.Platform.MauiView.SizeThatFits(CGSize size)
   at Microsoft.Maui.ViewHandlerExtensions.GetDesiredSizeFromHandler(IViewHandler viewHandler, Double widthConstraint, Double heightConstraint)
   at Microsoft.Maui.Handlers.ViewHandler`2[[Microsoft.Maui.ILayout, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Platform.LayoutView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].GetDesiredSize(Double widthConstraint, Double heightConstraint)
   at Microsoft.Maui.Layouts.LayoutExtensions.ComputeDesiredSize(IView view, Double widthConstraint, Double heightConstraint)
   at Microsoft.Maui.Controls.VisualElement.MeasureOverride(Double widthConstraint, Double heightConstraint)
   at Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.IView.Measure(Double widthConstraint, Double heightConstraint)
   at Microsoft.Maui.Layouts.VerticalStackLayoutManager.Measure(Double widthConstraint, Double heightConstraint)
   at Microsoft.Maui.Controls.Layout.CrossPlatformMeasure(Double widthConstraint, Double heightConstraint)
   at Microsoft.Maui.Platform.MauiView.CrossPlatformMeasure(Double widthConstraint, Double heightConstraint)
   at Microsoft.Maui.Platform.MauiView.LayoutSubviews()
   at Foundation.NSAttributedString..ctor(NSData data, NSDictionary options, NSDictionary& resultDocumentAttributes, NSError& error) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/dotnet/ios/generated-sources/Foundation/NSAttributedString.g.cs:line 165
   at Foundation.NSAttributedString..ctor(NSData data, NSAttributedStringDocumentAttributes options, NSDictionary& resultDocumentAttributes, NSError& error) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/dotnet/ios/generated-sources/Foundation/NSAttributedString.g.cs:line 179
   at Foundation.NSAttributedString..ctor(NSData data, NSAttributedStringDocumentAttributes documentAttributes, NSError& error) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/Foundation/NSAttributedString.cs:line 61
   at Microsoft.Maui.Platform.LabelExtensions.UpdateTextHtml(UILabel platformLabel, ILabel label)
   at Microsoft.Maui.Controls.Platform.LabelExtensions.UpdateText(UILabel platformLabel, Label label)
   at Microsoft.Maui.Controls.Label.MapText(ILabelHandler handler, Label label)
   at Microsoft.Maui.PropertyMapperExtensions.<>c__DisplayClass2_0`2[[Microsoft.Maui.Controls.Label, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Handlers.ILabelHandler, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].<ReplaceMapping>b__0(ILabelHandler h, Label v, Action`2 p)
   at Microsoft.Maui.PropertyMapperExtensions.<>c__DisplayClass1_0`2[[Microsoft.Maui.Controls.Label, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Handlers.ILabelHandler, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].<ModifyMapping>g__newMethod|0(IElementHandler handler, IElement view)
   at Microsoft.Maui.PropertyMapper`2.<>c__DisplayClass5_0[[Microsoft.Maui.ILabel, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Handlers.ILabelHandler, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].<Add>b__0(IElementHandler h, IElement v)
   at Microsoft.Maui.PropertyMapper.UpdatePropertyCore(String key, IElementHandler viewHandler, IElement virtualView)
   at Microsoft.Maui.PropertyMapper.UpdateProperties(IElementHandler viewHandler, IElement virtualView)
   at Microsoft.Maui.Handlers.ElementHandler.SetVirtualView(IElement view)
   at Microsoft.Maui.Handlers.ViewHandler`2[[Microsoft.Maui.ILabel, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Platform.MauiLabel, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].SetVirtualView(IView view)
   at Microsoft.Maui.Handlers.ViewHandler`2[[Microsoft.Maui.ILabel, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Platform.MauiLabel, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].SetVirtualView(IElement view)
   at Microsoft.Maui.Controls.Element.SetHandler(IElementHandler newHandler)
   at Microsoft.Maui.Controls.Element.set_Handler(IElementHandler value)
   at Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.IElement.set_Handler(IElementHandler value)
   at Microsoft.Maui.Platform.ElementExtensions.ToHandler(IElement view, IMauiContext context)
   at Microsoft.Maui.Platform.ElementExtensions.ToPlatform(IElement view, IMauiContext context)
   at Microsoft.Maui.Handlers.ContentViewHandler.UpdateContent(IContentViewHandler handler)
   at Microsoft.Maui.Handlers.ContentViewHandler.MapContent(IContentViewHandler handler, IContentView page)
   at Microsoft.Maui.PropertyMapper`2.<>c__DisplayClass5_0[[Microsoft.Maui.IContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Handlers.IContentViewHandler, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].<Add>b__0(IElementHandler h, IElement v)
   at Microsoft.Maui.PropertyMapper.UpdatePropertyCore(String key, IElementHandler viewHandler, IElement virtualView)
   at Microsoft.Maui.PropertyMapper.UpdateProperties(IElementHandler viewHandler, IElement virtualView)
   at Microsoft.Maui.Handlers.ElementHandler.SetVirtualView(IElement view)
   at Microsoft.Maui.Handlers.ViewHandler`2[[Microsoft.Maui.IContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Platform.ContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].SetVirtualView(IView view)
   at Microsoft.Maui.Handlers.ContentViewHandler.SetVirtualView(IView view)
   at Microsoft.Maui.Handlers.ViewHandler`2[[Microsoft.Maui.IContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.Platform.ContentView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].SetVirtualView(IElement view)
   at Microsoft.Maui.Controls.Element.SetHandler(IElementHandler newHandler)
   at Microsoft.Maui.Controls.Element.set_Handler(IElementHandler value)
   at Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.IElement.set_Handler(IElementHandler value)
   at Microsoft.Maui.Platform.ElementExtensions.ToHandler(IElement view, IMauiContext context)
   at Microsoft.Maui.Platform.ElementExtensions.ToPlatform(IElement view, IMauiContext context)
   at Microsoft.Maui.Handlers.LayoutHandler.Add(IView child)
   at Microsoft.Maui.Handlers.LayoutHandler.MapAdd(ILayoutHandler handler, ILayout layout, Object arg)
   at Microsoft.Maui.CommandMapper`2.<>c__DisplayClass6_0[[Microsoft.Maui.ILayout, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[Microsoft.Maui.ILayoutHandler, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].<Add>b__0(IElementHandler h, IElement v, Object o)
   at Microsoft.Maui.CommandMapper.InvokeCore(String key, IElementHandler viewHandler, IElement virtualView, Object args)
   at Microsoft.Maui.CommandMapper.Invoke(IElementHandler viewHandler, IElement virtualView, String property, Object args)
   at Microsoft.Maui.Handlers.ElementHandler.Invoke(String command, Object args)
   at Microsoft.Maui.Controls.Layout.NotifyHandler(String action, Int32 index, IView view)
   at Microsoft.Maui.Controls.Layout.OnAdd(Int32 index, IView view)
   at Microsoft.Maui.Controls.FlexLayout.OnAdd(Int32 index, IView view)
   at Microsoft.Maui.Controls.Layout.Add(IView child)
   at Microsoft.Maui.Controls.BindableLayout.Add(IBindableLayout layout, Object item)
   at Microsoft.Maui.Controls.BindableLayoutController.CreateChildren()
   at Microsoft.Maui.Controls.BindableLayoutController.SetItemsSource(IEnumerable itemsSource)
   at Microsoft.Maui.Controls.BindableLayoutController.set_ItemsSource(IEnumerable value)
   at Microsoft.Maui.Controls.BindableLayout.<>c.<.cctor>b__24_0(BindableObject b, Object o, Object n)
   at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, SetterSpecificity specificity, Boolean silent)
   at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, SetterSpecificity specificity)
   at Microsoft.Maui.Controls.BindingExpression.ApplyCore(Object sourceObject, BindableObject target, BindableProperty property, Boolean fromTarget, SetterSpecificity specificity)
   at Microsoft.Maui.Controls.BindingExpression.Apply(Object sourceObject, BindableObject target, BindableProperty property, SetterSpecificity specificity)
   at Microsoft.Maui.Controls.Binding.Apply(Object context, BindableObject bindObj, BindableProperty targetProperty, Boolean fromBindingContextChanged, SetterSpecificity specificity)
   at Microsoft.Maui.Controls.BindableObject.ApplyBindings(Boolean skipBindingContext, Boolean fromBindingContextChanged)
   at Microsoft.Maui.Controls.BindableObject.SetInheritedBindingContext(BindableObject bindable, Object value)
   at Microsoft.Maui.Controls.Element.SetChildInheritedBindingContext(Element child, Object context)
   at Microsoft.Maui.Controls.Element.<OnBindingContextChanged>b__89_0(BindableObject child, Object bc)
   at Microsoft.Maui.Controls.BindableObjectExtensions.PropagateBindingContext[Element](BindableObject self, IEnumerable`1 children, Action`2 setChildBindingContext)
   at Microsoft.Maui.Controls.Element.OnBindingContextChanged()
   at Microsoft.Maui.Controls.VisualElement.OnBindingContextChanged()
   at Microsoft.Maui.Controls.View.OnBindingContextChanged()
   at Microsoft.Maui.Controls.BindableObject.BindingContextPropertyChanged(BindableObject bindable, Object oldvalue, Object newvalue)
   at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, SetterSpecificity specificity, Boolean silent)
   at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, SetterSpecificity specificity)
   at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value)
   at Microsoft.Maui.Controls.BindableObject.set_BindingContext(Object value)
   at Microsoft.Maui.Controls.Handlers.Items.TemplatedCell.Bind(DataTemplate template, Object bindingContext, ItemsView itemsView)
   at Microsoft.Maui.Controls.Handlers.Items.ItemsViewController`1[[Microsoft.Maui.Controls.ReorderableItemsView, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].UpdateTemplatedCell(TemplatedCell cell, NSIndexPath indexPath)
   at Microsoft.Maui.Controls.Handlers.Items.ItemsViewController`1[[Microsoft.Maui.Controls.ReorderableItemsView, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].GetCell(UICollectionView collectionView, NSIndexPath indexPath)
   at UIKit.UICollectionView.InsertItems(NSIndexPath[] indexPaths) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/dotnet/ios/generated-sources/UIKit/UICollectionView.g.cs:line 478
   at Microsoft.Maui.Controls.Handlers.Items.ObservableItemsSource.<>c__DisplayClass42_0.<Add>b__0(UICollectionView c)
   at Microsoft.Maui.Controls.Handlers.Items.ObservableItemsSource.Update(Action`1 update, NotifyCollectionChangedEventArgs args)
   at Microsoft.Maui.Controls.Handlers.Items.ObservableItemsSource.Add(NotifyCollectionChangedEventArgs args)
   at Microsoft.Maui.Controls.Handlers.Items.ObservableItemsSource.CollectionChanged(NotifyCollectionChangedEventArgs args)
   at Microsoft.Maui.Controls.Handlers.Items.ObservableItemsSource.CollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   at System.Collections.ObjectModel.ObservableCollection`1[[CommunityToolkit.Mvvm.ComponentModel.ObservableObject, CommunityToolkit.Mvvm, Version=8.2.0.0, Culture=neutral, PublicKeyToken=4aff67a105548ee2]].OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   at System.Collections.ObjectModel.ObservableCollection`1[[CommunityToolkit.Mvvm.ComponentModel.ObservableObject, CommunityToolkit.Mvvm, Version=8.2.0.0, Culture=neutral, PublicKeyToken=4aff67a105548ee2]].OnCollectionChanged(NotifyCollectionChangedAction action, Object item, Int32 index)
   at System.Collections.ObjectModel.ObservableCollection`1[[CommunityToolkit.Mvvm.ComponentModel.ObservableObject, CommunityToolkit.Mvvm, Version=8.2.0.0, Culture=neutral, PublicKeyToken=4aff67a105548ee2]].InsertItem(Int32 index, ObservableObject item)
   at System.Collections.ObjectModel.Collection`1[[CommunityToolkit.Mvvm.ComponentModel.ObservableObject, CommunityToolkit.Mvvm, Version=8.2.0.0, Culture=neutral, PublicKeyToken=4aff67a105548ee2]].Add(ObservableObject item)
   at xxxViewModel.LoadonUIThread()
@Larhei Larhei added the t/bug Something isn't working label Apr 8, 2024
@Zhanglirong-Winnie Zhanglirong-Winnie added s/verified Verified / Reproducible Issue ready for Engineering Triage s/triaged Issue has been reviewed i/regression This issue described a confirmed regression on a currently supported version labels Apr 9, 2024
@Zhanglirong-Winnie
Copy link

Verified this issue with Visual Studio 17.10.0 Preview 2(8.0.10 & 8.0.14 & 8.0.40-nightly.10455+sha.998f884315-azdo.9383879). Can repro on iOS platform with sample project.
Maui.Controls 8.0.7 works fine.
image

@PureWeen PureWeen added this to the .NET 8 SR4 milestone Apr 9, 2024
@mattleibow
Copy link
Member

mattleibow commented Apr 9, 2024

I was able to narrow this down to a much simpler set of code:

FlexLayout flex = null!;
Content = new VerticalStackLayout
{
	new Button
	{
		Text = "GO!",
		Command = new Command(() =>
		{
			flex.Clear();
			var label = new Label
			{
				Text = "Hello",
				Background = Brush.Yellow,
				TextType = TextType.Html
			};
			flex.Add(label);
		})
	},
	(flex = new FlexLayout {  }),
};

If you click the button the first time, then it works. However, pressing it again causes it to throw the same error.

Seems _root is not null, but rather the flex item instance in the attached property. Having a look as to why the issue happens and why only in the second time.

@mattleibow
Copy link
Member

The reason the crash is appearing is because there is a "race" condition. It seems that the first time I add a label, all is well. However, the second time, setting the label text somehow triggers a layout of the UI which will try and layout the items... while they are being added.

   at Microsoft.Maui.Controls.FlexLayout.Layout(Double width, Double height)
   ...
   at Microsoft.Maui.Platform.MauiView.LayoutSubviews()
   at Foundation.NSAttributedString..ctor(NSData data, NSDictionary options, NSDictionary& resultDocumentAttributes, NSError& error) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/dotnet/ios/generated-sources/Foundation/NSAttributedString.g.cs:line 165
   at Foundation.NSAttributedString..ctor(NSData data, NSAttributedStringDocumentAttributes options, NSDictionary& resultDocumentAttributes, NSError& error) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/dotnet/ios/generated-sources/Foundation/NSAttributedString.g.cs:line 179
   at Foundation.NSAttributedString..ctor(NSData data, NSAttributedStringDocumentAttributes documentAttributes, NSError& error) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/Foundation/NSAttributedString.cs:line 61
   at Microsoft.Maui.Platform.LabelExtensions.UpdateTextHtml(UILabel platformLabel, ILabel label)
   ...
   at Microsoft.Maui.Controls.FlexLayout.OnAdd(Int32 index, IView view)

The last 2 lines are the setting of the text during the construction/addition of the label view. The first line is the start of a layout. In between, something causes a layout.

@Larhei
Copy link
Author

Larhei commented Apr 9, 2024

Hi @mattleibow, I was thinking the same when debugging this. But what is also interesting to me is that an add to the itemssource is generating an add in the flexlayout, than a clear/reset and than an add again.. I would have expected an single add would do it. But thanks looking into this and breaking it down

mattleibow added a commit that referenced this issue Apr 9, 2024
Fixes #21711

In some cases, adding an item before may trigger an update before
the add operation is complete. For example, adding a label with HTML
text may cause the layout to run while the label is being constructed.

To prevent that layout pass from crashing because the flex item is
not yet set, we make sure to first set the flex item, and then add it
to the layout. Then, when the layout pass runs, the item is ready to
be used.

This error might not typically appear in normal XAML layouts because
the items are first set, and then the entire page is inflated. However,
if the layout is part of a CollectionView or items are added
dynamically after the UI is loaded, this layout during add may occur.
@mattleibow
Copy link
Member

@Larhei do you have a sample of this:

Before Maui Version 8.0.14 this exception only happened when the Cell was not initial in the viewport and when scrolling it into view. So we changed our layout logic to have this cells in the viewport to not facing the issue.

I think my PR may fix that as it appeared adding items dynamically to the FlexLayout after it was visible would trigger issues. So, if you have a sample then I can test.

@Larhei
Copy link
Author

Larhei commented Apr 9, 2024

Hi @mattleibow, not right now. but in a few hours I try to build on.

@mattleibow mattleibow moved this from Todo to In Progress in MAUI SDK Ongoing Apr 10, 2024
@Larhei
Copy link
Author

Larhei commented Apr 10, 2024

Hi @mattleibow,

I added a Second Project to the Repository to showcase the issue.
I tried to rollback to 8.0.7 and provide a sample. I was unable to break it down to a "simple" Setup. Sorry.
But I was able to reproduce it with 8.0.3. And I understand the Setup is not simple. Sorry again.

Long story short.
Pull the Repro and launch Project FleyLayout1
Follow the Steps from the Recording.
https://github.com/dotnet/maui/assets/47631685/1e28bde0-8aa4-4ce5-b91a-dae50e6c4c6e

  1. Wait till List is populated
  2. Rotate Emulator by 90°
  3. Scroll a bit.
  4. Continue to rotate Emulator till back to 0°
  5. Crash should happen.

Callstack

Microsoft.Maui.Controls.FlexLayout.InitItemProperties(Microsoft.Maui.Controls.Border view, Microsoft.Maui.Layouts.Flex.Item item) in 
Microsoft.Maui.Controls.FlexLayout.EnsureFlexItemPropertiesUpdated() in 
Microsoft.Maui.Controls.FlexLayout.Layout(double width, double height) in 
Microsoft.Maui.Layouts.FlexLayoutManager.Measure(double widthConstraint, double heightConstraint) in 
Microsoft.Maui.Controls.FlexLayout.CrossPlatformMeasure(double widthConstraint, double heightConstraint) in 
Microsoft.Maui.Platform.MauiView.CrossPlatformMeasure(double widthConstraint, double heightConstraint) in 
Microsoft.Maui.Platform.MauiView.SizeThatFits(CoreGraphics.CGSize size) in 
Microsoft.Maui.ViewHandlerExtensions.GetDesiredSizeFromHandler(Microsoft.Maui.Handlers.LayoutHandler viewHandler, double widthConstraint, double heightConstraint) in 
Microsoft.Maui.Handlers.ViewHandler<Microsoft.Maui.ILayout,Microsoft.Maui.Platform.LayoutView>.GetDesiredSize(double widthConstraint, double heightConstraint) in 
Microsoft.Maui.Layouts.LayoutExtensions.ComputeDesiredSize(Microsoft.Maui.Controls.FlexLayout view, double widthConstraint, double heightConstraint) in 
Microsoft.Maui.Controls.VisualElement.MeasureOverride(double widthConstraint, double heightConstraint) in 
Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.IView.Measure(double widthConstraint, double heightConstraint) in 
Microsoft.Maui.Layouts.VerticalStackLayoutManager.Measure(double widthConstraint, double heightConstraint) in 
Microsoft.Maui.Controls.Layout.CrossPlatformMeasure(double widthConstraint, double heightConstraint) in 
Microsoft.Maui.Platform.MauiView.CrossPlatformMeasure(double widthConstraint, double heightConstraint) in 
Microsoft.Maui.Platform.MauiView.LayoutSubviews() in 
ObjCRuntime.Messaging.NativeHandle_objc_msgSend_NativeHandle_NativeHandle_ref_NativeHandle_ref_NativeHandle() in 
Foundation.NSAttributedString..ctor(Foundation.NSData data, Foundation.NSMutableDictionary options, Foundation.NSDictionary resultDocumentAttributes, Foundation.NSError error) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/dotnet/ios/generated-sources/Foundation/NSAttributedString.g.cs:165
Foundation.NSAttributedString..ctor(Foundation.NSData data, Foundation.NSAttributedStringDocumentAttributes options, Foundation.NSDictionary resultDocumentAttributes, Foundation.NSError error) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/dotnet/ios/generated-sources/Foundation/NSAttributedString.g.cs:179
Foundation.NSAttributedString..ctor(Foundation.NSData data, Foundation.NSAttributedStringDocumentAttributes documentAttributes, Foundation.NSError error) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/Foundation/NSAttributedString.cs:61
Microsoft.Maui.Platform.LabelExtensions.UpdateTextHtml(Microsoft.Maui.Platform.MauiLabel platformLabel, Microsoft.Maui.Controls.Label label) in 
Microsoft.Maui.Controls.Platform.LabelExtensions.UpdateText(Microsoft.Maui.Platform.MauiLabel platformLabel, Microsoft.Maui.Controls.Label label) in 
Microsoft.Maui.Controls.Label.MapText(Microsoft.Maui.Handlers.LabelHandler handler, Microsoft.Maui.Controls.Label label) in 
Microsoft.Maui.PropertyMapperExtensions.<>c__DisplayClass2_0<Microsoft.Maui.Controls.Label,Microsoft.Maui.Handlers.(Microsoft.Maui.Handlers.LabelHandler h, Microsoft.Maui.Controls.Label v, System.Action<Microsoft.Maui.IElementHandler,Microsoft.Maui.IElement> p) in 
Microsoft.Maui.PropertyMapperExtensions.<>c__DisplayClass1_0<Microsoft.Maui.Controls.Label,Microsoft.Maui.Handlers.(Microsoft.Maui.Handlers.LabelHandler handler, Microsoft.Maui.Controls.Label view) in 
Microsoft.Maui.PropertyMapper<Microsoft.Maui.ILabel,Microsoft.Maui.Handlers.ILabelHandler>.(Microsoft.Maui.Handlers.LabelHandler h, Microsoft.Maui.Controls.Label v) in 
Microsoft.Maui.PropertyMapper.UpdatePropertyCore(string key, Microsoft.Maui.Handlers.LabelHandler viewHandler, Microsoft.Maui.Controls.Label virtualView) in 
Microsoft.Maui.PropertyMapper.UpdateProperties(Microsoft.Maui.Handlers.LabelHandler viewHandler, Microsoft.Maui.Controls.Label virtualView) in 
Microsoft.Maui.Handlers.ElementHandler.SetVirtualView(Microsoft.Maui.Controls.Label view) in 
Microsoft.Maui.Handlers.ViewHandler<Microsoft.Maui.ILabel,Microsoft.Maui.Platform.MauiLabel>.SetVirtualView(Microsoft.Maui.Controls.Label view) in 
Microsoft.Maui.Handlers.ViewHandler<Microsoft.Maui.ILabel,Microsoft.Maui.Platform.MauiLabel>.SetVirtualView(Microsoft.Maui.Controls.Label view) in 
Microsoft.Maui.Controls.Element.SetHandler(Microsoft.Maui.Handlers.LabelHandler newHandler) in 
Microsoft.Maui.Controls.Element.set_Handler(Microsoft.Maui.Handlers.LabelHandler value) in 
Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.IElement.set_Handler(Microsoft.Maui.Handlers.LabelHandler value) in 
Microsoft.Maui.Platform.ElementExtensions.ToHandler(Microsoft.Maui.Controls.Label view, Microsoft.Maui.MauiContext context) in 
Microsoft.Maui.Platform.ElementExtensions.ToPlatform(Microsoft.Maui.Controls.Label view, Microsoft.Maui.MauiContext context) in 
Microsoft.Maui.Handlers.BorderHandler.UpdateContent(Microsoft.Maui.Handlers.BorderHandler handler) in 
Microsoft.Maui.Handlers.BorderHandler.MapContent(Microsoft.Maui.Handlers.BorderHandler handler, Microsoft.Maui.Controls.Border border) in 
Microsoft.Maui.PropertyMapper<Microsoft.Maui.IBorderView,Microsoft.Maui.Handlers.IBorderHandler>.(Microsoft.Maui.Handlers.BorderHandler h, Microsoft.Maui.Controls.Border v) in 
Microsoft.Maui.PropertyMapper.UpdatePropertyCore(string key, Microsoft.Maui.Handlers.BorderHandler viewHandler, Microsoft.Maui.Controls.Border virtualView) in 
Microsoft.Maui.PropertyMapper.UpdateProperties(Microsoft.Maui.Handlers.BorderHandler viewHandler, Microsoft.Maui.Controls.Border virtualView) in 
Microsoft.Maui.Handlers.ElementHandler.SetVirtualView(Microsoft.Maui.Controls.Border view) in 
Microsoft.Maui.Handlers.ViewHandler<Microsoft.Maui.IBorderView,Microsoft.Maui.Platform.ContentView>.SetVirtualView(Microsoft.Maui.Controls.Border view) in 
Microsoft.Maui.Handlers.BorderHandler.SetVirtualView(Microsoft.Maui.Controls.Border view) in 
Microsoft.Maui.Handlers.ViewHandler<Microsoft.Maui.IBorderView,Microsoft.Maui.Platform.ContentView>.SetVirtualView(Microsoft.Maui.Controls.Border view) in 
Microsoft.Maui.Controls.Element.SetHandler(Microsoft.Maui.Handlers.BorderHandler newHandler) in 
Microsoft.Maui.Controls.Element.set_Handler(Microsoft.Maui.Handlers.BorderHandler value) in 
Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.IElement.set_Handler(Microsoft.Maui.Handlers.BorderHandler value) in 
Microsoft.Maui.Platform.ElementExtensions.ToHandler(Microsoft.Maui.Controls.Border view, Microsoft.Maui.MauiContext context) in 
Microsoft.Maui.Platform.ElementExtensions.ToPlatform(Microsoft.Maui.Controls.Border view, Microsoft.Maui.MauiContext context) in 
Microsoft.Maui.Handlers.LayoutHandler.Add(Microsoft.Maui.Controls.Border child) in 
Microsoft.Maui.Handlers.LayoutHandler.MapAdd(Microsoft.Maui.Handlers.LayoutHandler handler, Microsoft.Maui.Controls.FlexLayout layout, Microsoft.Maui.Handlers.LayoutHandlerUpdate arg) in 
Microsoft.Maui.CommandMapper<Microsoft.Maui.ILayout,Microsoft.Maui.ILayoutHandler>.(Microsoft.Maui.Handlers.LayoutHandler h, Microsoft.Maui.Controls.FlexLayout v, Microsoft.Maui.Handlers.LayoutHandlerUpdate o) in 
Microsoft.Maui.CommandMapper.InvokeCore(string key, Microsoft.Maui.Handlers.LayoutHandler viewHandler, Microsoft.Maui.Controls.FlexLayout virtualView, Microsoft.Maui.Handlers.LayoutHandlerUpdate args) in 
Microsoft.Maui.CommandMapper.Invoke(Microsoft.Maui.Handlers.LayoutHandler viewHandler, Microsoft.Maui.Controls.FlexLayout virtualView, string property, Microsoft.Maui.Handlers.LayoutHandlerUpdate args) in 
Microsoft.Maui.Handlers.ElementHandler.Invoke(string command, Microsoft.Maui.Handlers.LayoutHandlerUpdate args) in 
Microsoft.Maui.Controls.Layout.NotifyHandler(string action, int index, Microsoft.Maui.Controls.Border view) in 
Microsoft.Maui.Controls.Layout.OnAdd(int index, Microsoft.Maui.Controls.Border view) in 
Microsoft.Maui.Controls.FlexLayout.OnAdd(int index, Microsoft.Maui.Controls.Border view) in 
Microsoft.Maui.Controls.Layout.Add(Microsoft.Maui.Controls.Border child) in 
Microsoft.Maui.Controls.BindableLayout.Add(Microsoft.Maui.Controls.FlexLayout layout, Microsoft.Maui.Controls.Border item) in 
Microsoft.Maui.Controls.BindableLayoutController.CreateChildren() in 
Microsoft.Maui.Controls.BindableLayoutController.SetItemsSource(System.Collections.ObjectModel.ObservableCollection<string> itemsSource) in 
Microsoft.Maui.Controls.BindableLayoutController.set_ItemsSource(System.Collections.ObjectModel.ObservableCollection<string> value) in 
Microsoft.Maui.Controls.BindableLayout.<>c.<.cctor>b__24_0(Microsoft.Maui.Controls.FlexLayout b, System.Collections.ObjectModel.ObservableCollection<string> o, System.Collections.ObjectModel.ObservableCollection<string> n) in 
Microsoft.Maui.Controls.BindableObject.SetValueActual(Microsoft.Maui.Controls.BindableProperty property, Microsoft.Maui.Controls.BindableObject.BindablePropertyContext context, System.Collections.ObjectModel.ObservableCollection<string> value, bool currentlyApplying, Microsoft.Maui.Controls.Internals.SetValueFlags attributes, Microsoft.Maui.Controls.SetterSpecificity specificity, bool silent) in 
Microsoft.Maui.Controls.BindableObject.SetValueCore(Microsoft.Maui.Controls.BindableProperty property, System.Collections.ObjectModel.ObservableCollection<string> value, Microsoft.Maui.Controls.Internals.SetValueFlags attributes, Microsoft.Maui.Controls.BindableObject.SetValuePrivateFlags privateAttributes, Microsoft.Maui.Controls.SetterSpecificity specificity) in 
Microsoft.Maui.Controls.BindingExpression.ApplyCore(FlexLayout1.Tags sourceObject, Microsoft.Maui.Controls.FlexLayout target, Microsoft.Maui.Controls.BindableProperty property, bool fromTarget, Microsoft.Maui.Controls.SetterSpecificity specificity) in 
Microsoft.Maui.Controls.BindingExpression.Apply(FlexLayout1.Tags sourceObject, Microsoft.Maui.Controls.FlexLayout target, Microsoft.Maui.Controls.BindableProperty property, Microsoft.Maui.Controls.SetterSpecificity specificity) in 
Microsoft.Maui.Controls.Binding.Apply(FlexLayout1.Tags context, Microsoft.Maui.Controls.FlexLayout bindObj, Microsoft.Maui.Controls.BindableProperty targetProperty, bool fromBindingContextChanged, Microsoft.Maui.Controls.SetterSpecificity specificity) in 
Microsoft.Maui.Controls.BindableObject.ApplyBindings(bool skipBindingContext, bool fromBindingContextChanged) in 
Microsoft.Maui.Controls.BindableObject.SetInheritedBindingContext(Microsoft.Maui.Controls.FlexLayout bindable, FlexLayout1.Tags value) in 
Microsoft.Maui.Controls.Element.SetChildInheritedBindingContext(Microsoft.Maui.Controls.FlexLayout child, FlexLayout1.Tags context) in 
Microsoft.Maui.Controls.Element.<OnBindingContextChanged>b__89_0(Microsoft.Maui.Controls.FlexLayout child, FlexLayout1.Tags bc) in 
Microsoft.Maui.Controls.BindableObjectExtensions.PropagateBindingContext<Microsoft.Maui.Controls.Element>(Microsoft.Maui.Controls.VerticalStackLayout self, System.Collections.ObjectModel.ReadOnlyCollection<Microsoft.Maui.Controls.Element> children, System.Action<Microsoft.Maui.Controls.BindableObject,object> setChildBindingContext) in 
Microsoft.Maui.Controls.Element.OnBindingContextChanged() in 
Microsoft.Maui.Controls.VisualElement.OnBindingContextChanged() in 
Microsoft.Maui.Controls.View.OnBindingContextChanged() in 
Microsoft.Maui.Controls.BindableObject.BindingContextPropertyChanged(Microsoft.Maui.Controls.VerticalStackLayout bindable, FlexLayout1.Tags oldvalue, FlexLayout1.Tags newvalue) in 
Microsoft.Maui.Controls.BindableObject.SetValueActual(Microsoft.Maui.Controls.BindableProperty property, Microsoft.Maui.Controls.BindableObject.BindablePropertyContext context, FlexLayout1.Tags value, bool currentlyApplying, Microsoft.Maui.Controls.Internals.SetValueFlags attributes, Microsoft.Maui.Controls.SetterSpecificity specificity, bool silent) in 
Microsoft.Maui.Controls.BindableObject.SetValueCore(Microsoft.Maui.Controls.BindableProperty property, FlexLayout1.Tags value, Microsoft.Maui.Controls.Internals.SetValueFlags attributes, Microsoft.Maui.Controls.BindableObject.SetValuePrivateFlags privateAttributes, Microsoft.Maui.Controls.SetterSpecificity specificity) in 
Microsoft.Maui.Controls.BindableObject.SetValue(Microsoft.Maui.Controls.BindableProperty property, FlexLayout1.Tags value) in 
Microsoft.Maui.Controls.BindableObject.set_BindingContext(FlexLayout1.Tags value) in 
Microsoft.Maui.Controls.Handlers.Items.TemplatedCell.Bind(FlexLayout1.CustomTemplateSelector template, FlexLayout1.Tags bindingContext, Microsoft.Maui.Controls.CollectionView itemsView) in 
Microsoft.Maui.Controls.Handlers.Items.ItemsViewController<Microsoft.Maui.Controls.ReorderableItemsView>.UpdateTemplatedCell(Microsoft.Maui.Controls.Handlers.Items.VerticalCell cell, Foundation.NSIndexPath indexPath) in 
Microsoft.Maui.Controls.Handlers.Items.ItemsViewController<Microsoft.Maui.Controls.ReorderableItemsView>.GetCell(UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) in 
UIKit.UIApplication.xamarin_UIApplicationMain() in 
UIKit.UIApplication.UIApplicationMain(int argc, string[] argv, System.IntPtr principalClassName, System.IntPtr delegateClassName) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/UIKit/UIApplication.cs:58
UIKit.UIApplication.Main(string[] args, System.Type principalClass, System.RuntimeType delegateClass) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/UIKit/UIApplication.cs:94
FlexLayout1.Program.Main(string[] args) in /Users/lars/workspace/Maui-Issues/FlexLayout/FlexLayout1/Platforms/iOS/Program.cs:13

@mattleibow
Copy link
Member

OK, I will try test. I am seeing this:

Microsoft.Maui.Platform.MauiView.LayoutSubviews() in 
ObjCRuntime.Messaging.NativeHandle_objc_msgSend_NativeHandle_NativeHandle_ref_NativeHandle_ref_NativeHandle() in 
Foundation.NSAttributedString..ctor(Foundation.NSData data, Foundation.NSMutableDictionary options, Foundation.NSDictionary resultDocumentAttributes, Foundation.NSError error) in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/dotnet/ios/generated-sources/Foundation/NSAttributedString.g.cs:165

Which is basically the same issue. Instantiating the NSAttributedString triggers a layout - and we are still in the process of adding the child to the layout. So things explode. Hopefully after my PR you can delete any workarounds.

@mattleibow
Copy link
Member

I think this PR also fixed that issue. I tried the nugets from this PR and it seems to no longer crash.

PureWeen pushed a commit that referenced this issue Apr 10, 2024
* Init the flex item before adding it to the layout

Fixes #21711

In some cases, adding an item before may trigger an update before
the add operation is complete. For example, adding a label with HTML
text may cause the layout to run while the label is being constructed.

To prevent that layout pass from crashing because the flex item is
not yet set, we make sure to first set the flex item, and then add it
to the layout. Then, when the layout pass runs, the item is ready to
be used.

This error might not typically appear in normal XAML layouts because
the items are first set, and then the entire page is inflated. However,
if the layout is part of a CollectionView or items are added
dynamically after the UI is loaded, this layout during add may occur.

* This too

* UI tests

* AutomationId is important :)
@PureWeen
Copy link
Member

Thank you for letting us know @Larhei

@github-project-automation github-project-automation bot moved this from In Progress to Done in MAUI SDK Ongoing Apr 10, 2024
@github-actions github-actions bot locked and limited conversation to collaborators May 11, 2024
@samhouts samhouts added the area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter label Oct 3, 2024
@samhouts samhouts added the layout-flex FlexLayout issues label Oct 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter fixed-in-8.0.21 fixed-in-9.0.0-preview.4.10690 i/regression This issue described a confirmed regression on a currently supported version layout-flex FlexLayout issues platform/iOS 🍎 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working
Projects
Status: Done
Development

No branches or pull requests

5 participants