1

I had to add a custom renderer to my .Net MAUI app (iOS). The app crashes right after the splash screen, and the only error I can see is

2022-09-29 14:41:32.896 Xamarin.PreBuilt.iOS[41370:12914225] Could not resolve assembly Microsoft.VisualStudio.DesignTools.TapContract, Version=17.0.0.0, Culture=neutral, PublicKeyToken=null. Details: Could not load file or assembly '/var/mobile/Containers/Data/Application/114BDA8C-ED16-4E18-B706-8D492B7703EB/Documents/My_MobileApp.content/Microsoft.VisualStudio.DesignTools.TapContract.dll' or one of its dependencies.

Here is my code in MauiProgram.cs:

    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .UseMauiCompatibility()
                .ConfigureMauiHandlers((handlers) => {
    #if ANDROID
                    handlers.AddHandler(typeof(Shell), typeof(Platforms.Android.Renderers.MyShellRenderer));
    #elif IOS
                    handlers.AddHandler(typeof(Shell), typeof(Platforms.iOS.Renderers.MyShellRenderer));
    #endif
                })...

The app works on Android. It works on iOS if I remove this #elif IOS part, but of course then the custom renderer does not do its job.

Here is the renderer itself:

    using Microsoft.Maui.Controls.Handlers.Compatibility;
    using Microsoft.Maui.Controls.Platform.Compatibility;
    using UIKit;

    namespace My_MobileApp.Platforms.iOS.Renderers
    {
        internal class MyShellRenderer : ShellRenderer
        {
            protected override IShellItemRenderer CreateShellItemRenderer(ShellItem item)
            {
                var renderer = base.CreateShellItemRenderer(item);
                if (renderer != null)
                {
                    if (renderer is ShellItemRenderer shellItem)
                    {
                        var items = shellItem.TabBar.Items;
                        for (int i = 0; i < items.Length; i++)
                        {
                            if (items[i] == null) continue;
                            else
                            {
                                UITabBarItem item_temp = items[i] as UITabBarItem;
                                UIView view = item_temp.ValueForKey(new Foundation.NSString("view")) as UIView;
                                UILabel label = view.Subviews[0] as UILabel;
                                label.Lines = 2;
                                label.LineBreakMode = UILineBreakMode.WordWrap;
                                label.TextAlignment = UITextAlignment.Center;
                            }
                        }
                    }
                }
                return renderer;
            }
        }
    }
Cfun
  • 8,442
  • 4
  • 30
  • 62
David Shochet
  • 5,035
  • 11
  • 57
  • 105
  • Are you sure there is no other relevant error in the output logs? no extra info that could help troubleshoot? stack trace ? call stack ? – Cfun Sep 29 '22 at 21:00
  • @Cfun No stack. – David Shochet Sep 29 '22 at 21:28
  • have you tried to debug by putting breakpoint and step into your code? – Cfun Sep 29 '22 at 21:31
  • @Cfun OK, I found something. The exception is caused by line label.Lines = 2; because label is null. I wonder how this can be fixed... This code is used to allow 2-line TabBar tab title. – David Shochet Sep 29 '22 at 21:48
  • 1
    what element is at view.Subviews[1]? – Cfun Sep 29 '22 at 22:35
  • @Cfun That worked! The label does have now 2 lines. But label.TextAlignment = UITextAlignment.Center; does not provide centering... – David Shochet Sep 29 '22 at 23:14
  • You can rewrite a simple renderer to test if the change happens, the answer to this issue can help you:https://stackoverflow.com/questions/72404629/maui-customize-an-entry#:~:text=These%20are%20the,AddHandler%20in%20MauiProgram. – Zack Sep 30 '22 at 08:48

1 Answers1

0

The reason it's not working is because you need to add it with the compatibility Renderer method and not as handlers.

So your Renderer registration should look like:

#if ANDROID
                handlers.AddCompatibilityRenderer(typeof(Shell), typeof(Platforms.Android.Renderers.MyShellRenderer));
#elif IOS
                handlers.AddCompatibilityRenderer(typeof(Shell), typeof(Platforms.iOS.Renderers.MyShellRenderer));
#endif

Detailed information here: https://github.com/dotnet/maui/wiki/Using-Custom-Renderers-in-.NET-MAUI

halfer
  • 19,824
  • 17
  • 99
  • 186
FreakyAli
  • 13,349
  • 3
  • 23
  • 63
  • Thank you for your answer. I tried it. I get System.InvalidCastException: 'Specified cast is not valid.' In iOS, it happens in iOS/Program.cs, line UIApplication.Main(args, null, typeof(AppDelegate)); Any idea? – David Shochet Sep 30 '22 at 12:16
  • Also, please look here: https://github.com/dotnet/maui/issues/9229#issuecomment-1209540694. It states: All of the shell renderers were migrated to work off of IViewHandler so they are all compatible with AddHandler now and don't require AddCompatibilityRenderer – David Shochet Sep 30 '22 at 13:55
  • 3
    Wow apparently their documentation is always out of date – FreakyAli Sep 30 '22 at 18:28
  • So I wonder why it is not centering. Setting it to 2 lines and word wrap does work. So weird. – David Shochet Sep 30 '22 at 19:15
  • May be change the bg color of the view and see if its aligned correctly, it could be its already in the "Center" if you know what i mean – FreakyAli Sep 30 '22 at 21:14