Forum Xamarin.Forms

overrideuserinterfacestyle in map custom renderer (ioS) crashing

oregon39oregon39 Member ✭✭
edited February 18 in Xamarin.Forms

I have an iOS Custom Renderer and am toggling between dark and light mode using overrideuserinterfacestyle. The toggle button is in a navigation menu drawer. When I change the night/light mode while on the map page and then go to another page and toggle the night mode, the app crashes upon returning to the map. I'm using Message Center to send a message upon toggle to the custom map renderer, so I tried limiting the sending of the message to only when I'm on the map page through some conditions. This moved the issue and the app crashed when toggling on the map page. Is there a better way to do this? I'm looking to toggle overrideuserinterfacestyle based on a global navigation menu button.

Tagged:

Best Answer

  • ColeXColeX Member, Xamarin Team Xamurai
    edited February 23 Accepted Answer

    @oregon39 said:
    @ColeX Thanks for your response. I tried sending the message to the viewmodel and then having a bindable property send the night mode status to OnElementPropertyChanged in the Custom Renderer, but that didn't seem to work. We have the night mode toggle in the Navigation Drawer, and it changes everything in the app to night mode, and we want to avoid having a separate setting on the map page to make the map dark or light. Do you have any suggestions on how to achieve this without Message Center (which doesn't work in this situation)? In the sample app, how can I change the map color from the landing page?

    Every time you enter into map page , MapRenderer.OnElementChanged will trigger and you just need to set the mode according to the value Settings.Current.NightModeEnabled .

    The dark/light mode should change when map is going to appear , you don't need to change it from landing page .

Answers

  • oregon39oregon39 Member ✭✭
    edited February 19

    In my custom map renderer, I have the following within a code block subscribing to a message from Message Center. The message is sent from the navigation menu page when the night mode is toggled. The code in the following method is called in OnElementChanged(). I made it so the message is only sent when on the map page, by creating a flag based on navigatingTo and NavigatingFrom. It toggles effectively at first but then when navigating back to the the map it crashes when setting the OverrideUserInterfaceStyle again via this call to the Message Center.

    if (Settings.Current.NightModeEnabled)
    {
    OverrideUserInterfaceStyle = UIUserInterfaceSyle.Dark;
    }
    else
    {
    OverrideUserInterfaceStyle = UIUserInterfaceStyle.Light;
    }

  • ColeXColeX Member, Xamarin Team Xamurai

    @oregon39 Is there any crash message ? Could you clarify which line cause the error ?

    If possible could you provide us a basic , minimal sample to test ?


    Xamarin forums are migrating to a new home on Microsoft Q&A!
    We invite you to post new questions in the Xamarin forums’ new home on Microsoft Q&A!
    For more information, please refer to this sticky post.

  • oregon39oregon39 Member ✭✭

    @ColeX Thanks so much. I appreciate it. I'm not getting any crash message. I will code up an example based on this issue in the code base.

  • ColeXColeX Member, Xamarin Team Xamurai
    edited February 22

    @oregon39 said:
    @ColeX Thanks so much. I appreciate it. I'm not getting any crash message. I will code up an example based on this issue in the code base.

    That's fine , how can I find the code ?

  • oregon39oregon39 Member ✭✭
    edited February 22

    @ColeX Hi ColeX: Attached is a zip file of the sample app. In the actual app, we are using a Nav Drawer and can change the dark mode setting from the map page as well. But I have simulated the basic issue with this sample. It's only for iOS.

    If you change the dark mode initially, you can go to the map page and it will appear in night mode, but if you come back to the landing page and try to change the night mode setting, it crashes. As I noted before, in the actual app, I tried to account for this and send the Message Center night mode message only while on the map page (using NavigateTo and NavigateFrom), which moved the crash from the other page into the map page when toggling the night mode in the Nav Drawer. A crash message in the sample app exists. I expected it to be something to do with the CustomRenderer not being available at the time of setting the night mode and it is that. Anyway, below is the crash message and attached is the sample app. I hope this sample sufficiently illustrates the issue.

    Thanks so much!

    System.ObjectDisposedException: Cannot access a disposed object.
    Object name: 'CustomMapRenderer'.
    at Foundation.NSObject.get_SuperHandle () [0x00012] in /Library/Frameworks/Xamarin.iOS.framework/Versions/14.6.0.15/src/Xamarin.iOS/Foundation/NSObject2.cs:394
    at UIKit.UIView.set_OverrideUserInterfaceStyle (UIKit.UIUserInterfaceStyle value) [0x0004c] in /Library/Frameworks/Xamarin.iOS.framework/Versions/14.6.0.15/src/Xamarin.iOS/UIKit/UIView.g.cs:4439
    at CustomRenderer.iOS.CustomMapRenderer.b__8_0 (CustomRenderer.MessagingService arg1, CustomRenderer.MessagingServiceSendString arg2) [0x00029] in /Users/paulfjaranas/Documents/Map/iOS/CustomMapRenderer.cs:179
    at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.b__7_0 (System.Object state) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1021
    at Foundation.NSAsyncSynchronizationContextDispatcher.Apply () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/14.6.0.15/src/Xamarin.iOS/Foundation/NSAction.cs:178
    --- End of stack trace from previous location where exception was thrown ---

  • ColeXColeX Member, Xamarin Team Xamurai
    edited February 23

    The error happens because you are trying to subscribe the messaging center from a disposed page .

    The map view may be removed from memory by GC when you click back to the landing page , so calling method from a destroyed view causes the error .

    Solution

    Do not use Messaging center in LandingPage .

    private void NightMode_OnClicked(object sender, EventArgs e)
            {
                Settings.Current.NightModeEnabled = !Settings.Current.NightModeEnabled;
                //MessagingService.Current.SendMessage("SetNightModeMap", new MessagingServiceSendString());
            }
    

    To use Messaging center we have to ensure that the sender and subscriber both exist .


    Xamarin forums are migrating to a new home on Microsoft Q&A!
    We invite you to post new questions in the Xamarin forums’ new home on Microsoft Q&A!
    For more information, please refer to this sticky post.

  • oregon39oregon39 Member ✭✭
    edited February 23

    @ColeX Thanks for your response. I tried sending the message to the viewmodel and then having a bindable property send the night mode status to OnElementPropertyChanged in the Custom Renderer, but that didn't seem to work. We have the night mode toggle in the Navigation Drawer, and it changes everything in the app to night mode, and we want to avoid having a separate setting on the map page to make the map dark or light. Do you have any suggestions on how to achieve this without Message Center (which doesn't work in this situation)? In the sample app, how can I change the map color from the landing page?

  • ColeXColeX Member, Xamarin Team Xamurai
    edited February 23 Accepted Answer

    @oregon39 said:
    @ColeX Thanks for your response. I tried sending the message to the viewmodel and then having a bindable property send the night mode status to OnElementPropertyChanged in the Custom Renderer, but that didn't seem to work. We have the night mode toggle in the Navigation Drawer, and it changes everything in the app to night mode, and we want to avoid having a separate setting on the map page to make the map dark or light. Do you have any suggestions on how to achieve this without Message Center (which doesn't work in this situation)? In the sample app, how can I change the map color from the landing page?

    Every time you enter into map page , MapRenderer.OnElementChanged will trigger and you just need to set the mode according to the value Settings.Current.NightModeEnabled .

    The dark/light mode should change when map is going to appear , you don't need to change it from landing page .

  • oregon39oregon39 Member ✭✭
    edited February 23

    @ColeX Yes, that is true. However, the only issue is that the Navigation Drawer opens over the map page as well, and one can also toggle night mode on and off from there. This worked using Message Center but crashed the app upon going back to another page (the landing page in the sample app). When I put a flag (based on the NavigateTo and NavigateFrom in the viewmodel) to try to send a message with Message Center only when on the map page, for some reason that crashed the app on the map page while toggling the night mode in the Nav Drawer. Do you have any suggestions how I can handle the toggle in the Nav Drawer? My requirement is that there is only one setting and everything changes together, being set in the Nav Drawer with the toggle--and it opens over the map page as well.

  • oregon39oregon39 Member ✭✭
    edited February 23

    @ColeX It appears that the root issue is that the navigation drawer is being misused. A nav drawer is defined as "a UI panel that show's your app's main navigation menu." The night mode toggle shouldn't be in the nav drawer. If the night mode toggle were in a settings page, then no issue would exist. I suggested this to my team, and it was agreed that this was a good solution.

  • oregon39oregon39 Member ✭✭

    @ColeX Thanks so much for your time and effort with this issue! I appreciate it.

Sign In or Register to comment.