In this post, I want to share with you some lessons I learned about MAUI. In the last few months, I have been creating an application using NET8 MAUI. I faced a lot of issues and step-by-step I resolved most of them.
OnDisappearing
This method is called when the page disappears due to navigating away from the page within the app. It is not called when the app disappears due to an event external to the app (e.g., the user navigates to the home screen or another app, a phone call is received, the device is locked, and the device is turned off).
Like in the old Xamarin, I added this method
protected override void OnDisappearing()
{
Shell.Current.GoToAsync("..", true);
return base.OnBackButtonPressed();
}
With this code, the application goes back of 2 pages: one page from the system and another one because of the code. So, be careful what adding in this function.
Platform-specific XAML
Sometimes, I have to determine the behaviours of the application based on the platform. For example, if the application is running on Windows, I want to display a ContextMenu
. For this reason, have to know the platform.
Here, we have a VerticalStackLayout and it has an x:Name
set so that we can manipulate the contents of it by accessing it via the VerticalLayout
identifier in the code-behind.
<Grid RowDefinitions="*,4*">
<VerticalStackLayout
Grid.Row="0"
x:Name="VerticalLayout" />
</Grid>
Runtime decision
The simplest way to show platform-specific views is to make the appropriate calls in the code-behind based on the current runtime platform:
if (DeviceInfo.Platform == DevicePlatform.Android)
{
VerticalLayout.Add(new Android.ViewAndroid());
}
else if (DeviceInfo.Platform == DevicePlatform.iOS)
{
VerticalLayout.Add(new iOS.ViewiOS());
}
else if (DeviceInfo.Platform == DevicePlatform.macOS)
{
VerticalLayout.Add(new iOS.ViewMacCatalyst());
}
else if (DeviceInfo.Platform == DevicePlatform.WinUI)
{
VerticalLayout.Add(new iOS.ViewWindows());
}
The downside of this approach is that the resulting code will be available on all target platforms.
Conditional compilation
An alternative and slightly better approach compared to the runtime decision is to use conditional compilation instead:
#if ANDROID
VerticalLayout.Add(new Android.ViewAndroid());
#elif IOS
VerticalLayout.Add(new iOS.ViewiOS());
#elif MACCATALYST
VerticalLayout.Add(new MacCatalyst.ViewMacCatalyst());
#elif WINDOWS
VerticalLayout.Add(new Windows.ViewWindows());
#endif
The advantage of this is that only the appropriate calls end up in the compiled app code for each target platform and no decision needs to be taken during runtime.
XAML-only approach
It’s also possible to show only the relevant parts of the UI based on the current runtime platform by only using XAML and no C# code by taking advantage of <OnPlatform>
:
<Grid RowDefinitions="*,4*">
<ContentView
Grid.Row="1"
Padding="20">
<OnPlatform x:TypeArguments="View">
<On Platform="Android">
<android:ImageViewAndroid />
</On>
<On Platform="iOS">
<iOs:ImageViewiOS />
</On>
<On Platform="macOS">
<mac:ImageViewUWP />
</On>
<On Platform="Windows">
<windows:ImageViewUWP />
</On>
</OnPlatform>
</ContentView>
</Grid>
Here, we have a ContentView that serves as a container and we control its content by using the <OnPlatform>
class and providing different views for each platform. It’s important to include the x:TypeArguments="View"
attribute, because we need to tell <OnPlatform>
what the return type is as the ContentView
class only accepts View
instances as its Content
.
Note: This is equivalent to the runtime decision approach in the code-behind, meaning that all views of all platforms will be included in the app bundle.
It’s also possible to use <OnIdiom>
to provide different views depending on the device type (e.g. tablet, phone, desktop):
<Grid RowDefinitions="*,4*">
<ContentView
Grid.Row="1"
Padding="20">
<OnIdiom x:TypeArguments="View">
<On Idiom="Tablet">
<tablet:TabletView />
</On>
<On Idiom="Phone">
<phone:PhoneView />
</On>
</OnIdiom>
</ContentView>
</Grid>
MAUI and iOS: icon set or app icon set named “appicon” error
I would like to test it on an iOS simulator. When I try to run the application, I get this error
None of the input catalogs contained a matching stickers icon set or app icon set named “appicon”.
After binging a bit, I found this post on GitHub where they say:
In the info.plist you have
XSAppIconAssets Assets.xcassets/appicon.appiconset The AppIcon file name is icon.svg
What worked for me was making sure those name matched, ex rename the svg to appicon.svg or in info.plist to icon.appiconset
or
I had the same problem what fixed it for me was renaming my icon file from “orpheus_icon.png” to “orpheus.png” and changing this line in the info.plist to Assets.xcassets/orpheus.appiconset
Those answers were related to the NET7 and the previous version of MAUI. I think something has changed since then.
In my project, I have the folder Platform > iOS > AppIcon.appiconset and the autogenerated images. In Resources, I have the appicon.svg.
In the Info.plist, I have
<key>XSAppIconAssets</key>
<string>Assets.xcassets/appicon.appiconset</string>
Solution
Removing the bin
and obj
folders is not helping. The solution I found is to delete the Assets.appiconset
from the iOS
folder.
SecureStorage in Windows raises an error if saves an empty value
In my NET8
MAUI
app, I’m using SecureStorage
to save the user’s username. In Android, the function is working. I call the API to authenticate the user and as response, I get the UserId and UserName. Sometimes, the UserId is empty.
When I save the empty UserId with this code in Windows (working for Android)
await SecureStorage.Default.SetAsync("userId", login.UserId);
await SecureStorage.Default.SetAsync("username", login.UserName);
the app raises this error
System.ArgumentException: ‘Value does not fall within the expected range.’

Issue
This exception is coming from the implementation of the SecureStorage for Windows. It was caused by var buffer = await provider.ProtectAsync(bytes.AsBuffer());
. This should be a limit of the Windows native API. The null will also throw an exception about the value can’t be null.
So the string.Empty and null are not supported for the SecureStorage in the maui on the Windows platform.
Solution
I have to check if the value is not null and save only if it is not null. To remove a key use
SecureStorage.Default.Remove("userId");
and don’t try to add an empty string.
AppCenter crashes iOS application
In all my apps, I usually add AppCenter to track the events and the crashes. For this reason, I add the packages Microsoft.AppCenter.Analytics
and Microsoft.AppCenter.Crashes packages
to my projects. The issue is that when I try to deploy the application to an iOS Simulator I get this error:
clang++ exited with code 1: ld: in /Users/enrico/Library/Caches/Xamarin/mtbs/builds/LanguageInUse/1fa03704bb15e35c6f47a701d9d92131e3e0740198296a93338bb3c829bc9cf7/obj/Debug/net8.0-ios/iossimulator-arm64/linker-cache/AppCenterCrashes.a(MSACErrorReport.o), building for iOS Simulator, but linking in object file built for iOS, file ‘/Users/enrico/Library/Caches/Xamarin/mtbs/builds/LanguageInUse/1fa03704bb15e35c6f47a701d9d92131e3e0740198296a93338bb3c829bc9cf7/obj/Debug/net8.0-ios/iossimulator-arm64/linker-cache/AppCenterCrashes.a’ clang: error: linker command failed with exit code 1 (use -v to see invocation) LanguageInUse C:\Program Files\dotnet\packs\Microsoft.iOS.Sdk\17.2.8004\targets\Xamarin.Shared.Sdk.targets 1559
Also, I tried different Target iOS Framework
but I get the same result.
Solution
The underlying issue seems to be that the AppCenter NuGet doesn’t support the ARM64 architecture in the simulator. As shared in this MAUI GitHub issue, you have to enter this in your CSPROJ file:
<ForceSimulatorX64ArchitectureInIDE>true</ForceSimulatorX64ArchitectureInIDE>
Orange selected ListView item
Here is an issue with MAUI that made me crazy for almost 2 months. I added a ListView
on my page and displayed some data. When I tap on an item, the background color is orange.

This is a well-known issue in MAUI (see the issue on GitHub). To fix this issue, I had to create a custom ViewCell
for each platform. Because the solution is quite long, I created a post for it. Jump on Orange selected ListView item highlighted in MAUI to see the full implementation.
Publish an Android app warnings for deobfuscation and native code
When I upload an app bundle or apk
on the `Google Play console`, I get a warning
There is no deobfuscation file associated with this App Bundle. If you use obfuscated code (R8/proguard), uploading a deobfuscation file will make crashes and ANRs easier to analyse and debug. Using R8/proguard can help reduce app size.
This App Bundle contains native code, and you’ve not uploaded debug symbols. We recommend that you upload a symbol file to make your crashes and ANRs easier to analyse and debug.
Google Play console

So, the solution is to open the Properties of the project and then select the option for Android. There is a setting for R8 code shrinker. Check this option.
