CommunityToolkit / Maui

The .NET MAUI Community Toolkit is a community-created library that contains .NET MAUI Extensions, Advanced UI/UX Controls, and Behaviors to help make your life as a .NET MAUI developer easier
https://learn.microsoft.com/dotnet/communitytoolkit/maui
MIT License
2.07k stars 332 forks source link

[BUG] Toast.Show crashing on iOS Release builds #1752

Closed vouksh closed 1 month ago

vouksh commented 2 months ago

Is there an existing issue for this?

Did you read the "Reporting a bug" section on Contributing file?

Current Behavior

When attempting to show a Toast notification, an exception is thrown and no toast is displayed.

   at System.Collections.Frozen.SmallFrozenSet`1.GSW[[UIKit.UIView, Microsoft.iOS, Version=17.2.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065]].Store(FrozenSet`1 )
   at System.Collections.Frozen.FrozenSetInternalBase`2[[UIKit.UIView, Microsoft.iOS, Version=17.2.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065],[System.Collections.Frozen.SmallFrozenSet`1.GSW[[UIKit.UIView, Microsoft.iOS, Version=17.2.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065]], System.Collections.Immutable, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]]..ctor(IEqualityComparer`1 )
   at System.Collections.Frozen.SmallFrozenSet`1[[UIKit.UIView, Microsoft.iOS, Version=17.2.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065]]..ctor(HashSet`1 )
   at System.Collections.Frozen.FrozenSet.CreateFromSet[UIView](HashSet`1 )
   at System.Collections.Frozen.FrozenSet.ToFrozenSet[UIView](IEnumerable`1 , IEqualityComparer`1 )
   at CommunityToolkit.Maui.Core.Views.AlertView.get_Children()
   at CommunityToolkit.Maui.Core.Views.AlertView.Initialize()
   at CommunityToolkit.Maui.Core.Views.Alert.Show()
   at CommunityToolkit.Maui.Alerts.Toast.ShowPlatform(CancellationToken token)
   at CommunityToolkit.Maui.Alerts.Toast.Show(CancellationToken token)
   at KinesiaOne.ViewModels.SettingsPageViewModel.VersionTapped()

Expected Behavior

The toast pop-up should be shown.

Steps To Reproduce

  1. Clone the repository
  2. Set the Bundle ID to one that you have a Distribution certificate for
  3. Build as Release and push to a device
  4. Press the "Click me" button and see the exception and that there is no toast displayed

Link to public reproduction project repository

https://github.com/vouksh/CommunityToastBug

Environment

- .NET MAUI CommunityToolkit: 7.0.1
- OS: Windows 11 Build 22631.3155 23H2 | Paired to Intel MacBook Pro, macOS 14.3.1 - Xcode 15.2
- .NET MAUI: 8.0.10
- .NET: 8.0.202
- Visual Studio Community 17.9.3

Anything else?

This worked previously before updating Visual Studio and MAUI.

brminnick commented 2 months ago

May be related to this: https://github.com/dotnet/maui/issues/13019#issuecomment-1995427494

DDHSchmidt commented 2 months ago

The reference to the interpreter issue is definitely on the right track. In our case, we already had the following in our csproj:

<PropertyGroup Condition="$(Configuration.Contains('Release')) And $(TargetFramework.Contains('ios'))">
    <MtouchInterpreter>-all</MtouchInterpreter>
    <!-- Other properties -->
</PropertyGroup>

After seeing the same stacktrace as yours on Release and after assessing that "System.Collections.Frozen.FrozenSet" resides in the assembly "System.Collections.Immutable" we adjusted it to the following:

<PropertyGroup Condition="$(Configuration.Contains('Release')) And $(TargetFramework.Contains('ios'))">
    <MtouchInterpreter>-all,System.Collections.Immutable</MtouchInterpreter>
    <!-- Other properties -->
</PropertyGroup>

That got rid of the crash in Release builds for us.

brminnick commented 2 months ago

@bijington What are your thoughts about updating the docs to include the MtouchInterpreter snippet above from @DDHSchmidt as a required setup for Toast?

<PropertyGroup Condition="$(Configuration.Contains('Release')) And $(TargetFramework.Contains('ios'))">
    <MtouchInterpreter>-all,System.Collections.Immutable</MtouchInterpreter>
</PropertyGroup>

I'm thinking that we can add a Platform specific initialization section to the Toast docs, similar to the MediaElement docs:

image

And then once the linked bug is resolved in net-ios, we could remove the Platform specific initialization from the Toast docs.

mjo151 commented 1 month ago

I am also seeing this problem, and it occurs when trying to display either a Snackbar or Toast on a release build on iOS. The odd thing is that Snackbar and Toast have been working fine for me for a while. I suspect that the problem is caused by the .NET 8.0.3 release (SDK version 8.0.202), as I updated to that recently.

bijington commented 1 month ago

@bijington What are your thoughts about updating the docs to include the MtouchInterpreter snippet above from @DDHSchmidt as a required setup for Toast?

<PropertyGroup Condition="$(Configuration.Contains('Release')) And $(TargetFramework.Contains('ios'))">
  <MtouchInterpreter>-all,System.Collections.Immutable</MtouchInterpreter>
</PropertyGroup>

I'm thinking that we can add a Platform specific initialization section to the Toast docs, similar to the MediaElement docs:

image

And then once the linked bug is resolved in net-ios, we could remove the Platform specific initialization from the Toast docs.

That might be a helpful idea

mjo151 commented 1 month ago

This problem appears to be caused by the use of FrozenSet in AlertView.macios.cs. If you look at the stack trace, it's occurring in AlertView.Initialize, where the Children property is being enumerated. I am thinking that changing the foreach loop to access the children field instead of the Children property will fix the problem and prevent having to instruct users to enable the interpreter to use these features.

plppp2001 commented 1 month ago

I am also seeing this problem, and it occurs when trying to display either a Snackbar or Toast on a release build on iOS. The odd thing is that Snackbar and Toast have been working fine for me for a while. I suspect that the problem is caused by the .NET 8.0.3 release (SDK version 8.0.202), as I updated to that recently.

Same here, it crashed my new ios app Release build.

HaimoHeymann commented 1 month ago

I followed the suggestion and added these lines to my MauiToast.csproj

<PropertyGroup Condition="$(Configuration.Contains('Release')) And $(TargetFramework.Contains('ios'))">
    <MtouchInterpreter>-all,System.Collections.Immutable</MtouchInterpreter>
</PropertyGroup>

Now the app crashes already while booting ...

ScarletKuro commented 1 month ago

Have people tried

<MtouchLink>SdkOnly</MtouchLink>
<UseInterpreter>True</UseInterpreter>

? I believe this should work if people say it's crashing only in release mode and I remember some folks from MS said this should be considered as default for release builds on iOS https://github.com/dotnet/maui/issues/13019 There are too much features that require interpreter anyway. A year ago AOT without UseInterpreter was unusable, I don't think anything much changed since then.

mjo151 commented 1 month ago

I submitted PR #1767 that fixes this issue and doesn't require enabling the interpreter.

jspuij commented 1 month ago

I followed the suggestion and added these lines to my MauiToast.csproj

<PropertyGroup Condition="$(Configuration.Contains('Release')) And $(TargetFramework.Contains('ios'))">
  <MtouchInterpreter>-all,System.Collections.Immutable</MtouchInterpreter>
</PropertyGroup>

Now the app crashes already while booting ...

Did you include the conditions? Because the app crashes on boot if you combine <UseInterpreter>true</UseInterpreter> with <MtouchInterpreter>-all,System.Collections.Immutable</MtouchInterpreter> and UseInterpreter is enabled in debug builds.

janusw commented 1 month ago

This is pretty severe. Any chance there will be a version 8.0.2 with the fix from #1767 anytime soon?

durandt commented 1 month ago

[Redacted irrelevant stuff]

janusw commented 1 month ago

This is pretty severe. Any chance there will be a version 8.0.2 with the fix from #1767 anytime soon?

@janusw have you seen the mitigations/work-arounds in dotnet/maui#18692 ?

@durandt That does not sound related at all. Do you mean a different issue, maybe?

durandt commented 1 month ago

@janusw Oh entschuldigung indeed, very confused :D Nevermind what I wrote there...

ivanpovazan commented 4 weeks ago

Even though this issue is closed, the problem with FrozenSet seems to be fixed in .NET9 and the workaround for enabling the interpreter is not needed anymore.

For those who were affected with it, you can try the latest .NET9 preview release to verify if it fixed the problem for you?

plppp2001 commented 4 weeks ago

Even though this issue is closed, the problem with FrozenSet seems to be fixed in .NET9 and the workaround for enabling the interpreter is not needed anymore.

For those who were affected with it, you can try the latest .NET9 preview release to verify if it fixed the problem for you?

Some companies do not allow Pre Releases in Production. Will it be released within the .NET 8 timeline? @janusw

ivanpovazan commented 4 weeks ago

Some companies do not allow Pre Releases in Production. Will it be released within the .NET 8 timeline?

Yes, thanks for pointing that out. That was the reason I asked if affected customers can try the .NET9 preview versions. If the problem is fixed for them we can investigate backporting the fixes to .NET8 so they become available in a servicing release. Otherwise, the workaround would have to be used until .NET9 is released.

janusw commented 3 weeks ago

Even though this issue is closed, the problem with FrozenSet seems to be fixed in .NET9 and the workaround for enabling the interpreter is not needed anymore.

For those who were affected with it, you can try the latest .NET9 preview release to verify if it fixed the problem for you?

@ivanpovazan I just ran the case that triggered this bug with .NET 9 (SDK 9.0.100-preview.3.24204.13, MAUI 9.0.0-preview.3.10457), and indeed it seems like that fixes the crashes in iOS Release builds.

So, yes, the FrozenSet fixes in .NET 9 seem to work AFAICT. A backport to .NET 8 would be very welcome! :+1:

janusw commented 3 weeks ago

@ivanpovazan I just ran the case that triggered this bug with .NET 9 (SDK 9.0.100-preview.3.24204.13, MAUI 9.0.0-preview.3.10457), and indeed it seems like that fixes the crashes in iOS Release builds.

In fact it looks like it's enough to use the preview version of the .NET 9 SDK, even when sticking to net8.0 targets and MAUI 8.0.x packages.

janusw commented 3 weeks ago

For the record: Another workaround that I found by accident is putting the following into the csproj ...

    <Target Name="UpdateRuntimePackVersion" BeforeTargets="ProcessFrameworkReferences">
      <ItemGroup>
        <KnownRuntimePack Condition="%(RuntimePackLabels) == 'Mono'" LatestRuntimeFrameworkVersion="8.0.2" />
      </ItemGroup>
    </Target>

I originally used this as a workaround for another .NET runtime issue (using runtime version 8.0.0). After that one was fixed, I tried to remove the workaround and hit the crashes with Toast / Snackbar.

Note that runtime versions 8.0.0, 8.0.1 and 8.0.2 work well, while 8.0.3 and 8.0.4 trigger the crash. In that sense it's a regression, i.e. one more reason to fix it on 8.0.

zhitaop commented 3 weeks ago

We are seeing a similar crash in our app iOS release build when using the MathExpressionConverter, as shown by the stack trace below:

System.Collections.Frozen.DefaultFrozenSet`1.GSW[[CommunityToolkit.Maui.Core.MathOperator, CommunityToolkit.Maui.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].Store(FrozenSet`1 )
System.Collections.Frozen.FrozenSetInternalBase`2[[CommunityToolkit.Maui.Core.MathOperator, CommunityToolkit.Maui.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Collections.Frozen.DefaultFrozenSet`1.GSW[[CommunityToolkit.Maui.Core.MathOperator, CommunityToolkit.Maui.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Collections.Immutable, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]]..ctor(IEqualityComparer`1 )
System.Collections.Frozen.ItemsFrozenSet`2[[CommunityToolkit.Maui.Core.MathOperator, CommunityToolkit.Maui.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Collections.Frozen.DefaultFrozenSet`1.GSW[[CommunityToolkit.Maui.Core.MathOperator, CommunityToolkit.Maui.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Collections.Immutable, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]]..ctor(HashSet`1 , Boolean )
System.Collections.Frozen.DefaultFrozenSet`1[[CommunityToolkit.Maui.Core.MathOperator, CommunityToolkit.Maui.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]..ctor(HashSet`1 )
System.Collections.Frozen.FrozenSet.CreateFromSet[MathOperator](HashSet`1 )
System.Collections.Frozen.FrozenSet.ToFrozenSet[MathOperator](IEnumerable`1 , IEqualityComparer`1 )
CommunityToolkit.Maui.Converters.MathExpression..ctor(String expression, IEnumerable`1 arguments)
CommunityToolkit.Maui.Converters.MathExpressionConverter.ConvertFrom(Double value, String parameter, CultureInfo culture)
ivanpovazan commented 3 weeks ago

@janusw thank you for providing the additional information. I opened https://github.com/dotnet/runtime/issues/101427 for tracking.

janusw commented 3 weeks ago

I opened dotnet/runtime#101427 for tracking.

@ivanpovazan Awesome, thank you. Apparently you even identified the origin of the problem already, so I guess there is hope that it can be fixed soon 🥳