Preferences : New/Save/Load

I found one example in the MonoMac samples, but it doesn't appear to build, showing various errors. Is there a concise example showing how to handle preferences (new user, save, load, migration) under Mono on OS X?

Tagged:

Best Answer

Answers

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    Can you point us to the "broken" sample?

    @KMullins - This sounds like a reasonable documentation request.

  • philstopfordphilstopford USMember

    The 'Preferences' project is misleading because it actually doesn't appear to create/store/retrieve preference data - it only shows the preference panel UI implementation.

    Hunting around, the CFNetwork sample looked more useful, but it complains about AsyncTests not being found. Adding those references in (they are part of the complex sample), the build of AsyncTests then complains about Mono.Addins not being found (referenced in TestSuite.cs).

    Not being able to build the sample, I hunted around and it looks like the main work is done in PreferencesController.cs, but I don't see how the system handles the non-existence of preferences. Trying to replicate the approach in a test application, I always get a crash at startup. A concise example would be very welcome.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    So, I believe the magic happens here:

    https://github.com/xamarin/mac-samples/blob/master/CFNetwork/Views/PreferencesController.cs#L119

    We create a dictionary of all of the default values and register it w/ the system as the defaults.

    We then load the defaults back to setup our UI:

    https://github.com/xamarin/mac-samples/blob/master/CFNetwork/Views/PreferencesController.cs#L124

    And then when we close, we can save out any changes via:

    https://github.com/xamarin/mac-samples/blob/master/CFNetwork/Views/PreferencesController.cs#L144

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai
  • philstopfordphilstopford USMember
    edited October 2015

    Hmm. So here's my code snippet from my test case. The application crashes when this is registered (and it seems to take quite a while to do so).

            public void registerDefaults ()
            {
                var dict = new NSMutableDictionary ();
                dict ["layer1_Color"] = NSColor.FromDeviceRgba (this.mcGen2Context.colors.default_layer1_Color.R/255.0f,
                    this.mcGen2Context.colors.default_layer1_Color.G/255.0f, this.mcGen2Context.colors.default_layer1_Color.B/255.0f,
                    this.mcGen2Context.colors.default_layer1_Color.A/255.0f);
    
                dict ["layer2_Color"] = NSColor.FromDeviceRgba (this.mcGen2Context.colors.default_layer2_Color.R/255.0f,
                    this.mcGen2Context.colors.default_layer2_Color.G/255.0f, this.mcGen2Context.colors.default_layer2_Color.B/255.0f,
                    this.mcGen2Context.colors.default_layer2_Color.A/255.0f);
                dict ["layer3_Color"] = NSColor.FromDeviceRgba (this.mcGen2Context.colors.default_layer3_Color.R/255.0f,
                    this.mcGen2Context.colors.default_layer3_Color.G/255.0f, this.mcGen2Context.colors.default_layer3_Color.B/255.0f,
                    this.mcGen2Context.colors.default_layer3_Color.A/255.0f);
                dict ["layer4_Color"] = NSColor.FromDeviceRgba (this.mcGen2Context.colors.default_layer4_Color.R/255.0f,
                    this.mcGen2Context.colors.default_layer4_Color.G/255.0f, this.mcGen2Context.colors.default_layer4_Color.B/255.0f,
                    this.mcGen2Context.colors.default_layer4_Color.A/255.0f);
    
                dict ["layer12_Color"] = NSColor.FromDeviceRgba (this.mcGen2Context.colors.default_layer12_Color.R/255.0f,
                    this.mcGen2Context.colors.default_layer12_Color.G/255.0f, this.mcGen2Context.colors.default_layer12_Color.B/255.0f,
                    this.mcGen2Context.colors.default_layer12_Color.A/255.0f);
                dict ["layer34_Color"] = NSColor.FromDeviceRgba (this.mcGen2Context.colors.default_layer34_Color.R/255.0f,
                    this.mcGen2Context.colors.default_layer34_Color.G/255.0f, this.mcGen2Context.colors.default_layer34_Color.B/255.0f,
                    this.mcGen2Context.colors.default_layer34_Color.A/255.0f);
    
                dict ["result_Color"] = NSColor.FromDeviceRgba (this.mcGen2Context.colors.default_result_Color.R/255.0f,
                    this.mcGen2Context.colors.default_result_Color.G/255.0f, this.mcGen2Context.colors.default_result_Color.B/255.0f,
                    this.mcGen2Context.colors.default_result_Color.A/255.0f);
                dict ["result2_Color"] = NSColor.FromDeviceRgba (this.mcGen2Context.colors.default_result2_Color.R/255.0f,
                    this.mcGen2Context.colors.default_result2_Color.G/255.0f, this.mcGen2Context.colors.default_result2_Color.B/255.0f,
                    this.mcGen2Context.colors.default_result2_Color.A/255.0f);
                dict ["result3_Color"] = NSColor.FromDeviceRgba (this.mcGen2Context.colors.default_result3_Color.R/255.0f,
                    this.mcGen2Context.colors.default_result3_Color.G/255.0f, this.mcGen2Context.colors.default_result3_Color.B/255.0f,
                    this.mcGen2Context.colors.default_result3_Color.A/255.0f);
                dict ["result4_Color"] = NSColor.FromDeviceRgba (this.mcGen2Context.colors.default_result4_Color.R/255.0f,
                    this.mcGen2Context.colors.default_result4_Color.G/255.0f, this.mcGen2Context.colors.default_result4_Color.B/255.0f,
                    this.mcGen2Context.colors.default_result4_Color.A/255.0f);
    
                this.mcGen2Context.colors.rebuildLists();
    
                dict ["emailAddress"] = (NSString) this.mcGen2Context.emailAddress;
                dict ["emailPwd"] = (NSString) this.mcGen2Context.emailPwd;
                dict ["emailServer"] = (NSString) this.mcGen2Context.host;
                dict ["emailPort"] = (NSString) this.mcGen2Context.port;
                dict ["emailSSL"] = NSNumber.FromBoolean(this.mcGen2Context.ssl);
    
                dict ["emailCompletion"] = NSNumber.FromBoolean(this.mcGen2Context.completion);
                dict ["emailPerJob"] = NSNumber.FromBoolean(this.mcGen2Context.perJob);
    
                try
                {
                    NSUserDefaults.StandardUserDefaults.RegisterDefaults (dict);
        }
            catch (Exception)
            {
                }
            }
    

    A breakpoint on the exception isn't caught - the application just crashes out. The referenced values all look fine if I review them

  • philstopfordphilstopford USMember

    Something's gone funky with the formatting; it's like chasing dials to fix it. Hopefully it's clear enough.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    Can you post the crash stack?

  • philstopfordphilstopford USMember
    edited October 2015

    Crashed Thread: 3

    Exception Type: EXC_BAD_ACCESS (SIGABRT)
    Exception Codes: KERN_INVALID_ADDRESS at 0x00000000850fc138
    Exception Note: EXC_CORPSE_NOTIFY

    Thread 3 Crashed:
    0   libsystem_kernel.dylib          0x960dc62a __pthread_kill + 10
    1   libsystem_pthread.dylib         0x9db3b664 pthread_kill + 101
    2   libsystem_c.dylib               0x9ab068c8 abort + 156
    3   libmono-2.0.dylib               0x00c236e5 mono_handle_native_sigsegv + 757
    4   libmono-2.0.dylib               0x00c708d2 mono_arch_handle_altstack_exception + 162 (exceptions-x86.c:1107)
    5   libmono-2.0.dylib               0x00b71ee3 mono_sigsegv_signal_handler + 467 (mini-runtime.c:2468)
    6   libsystem_platform.dylib        0x9820e79b _sigtramp + 43
    7   ???                             0xffffffff 0 + 4294967295
    8   libmono-2.0.dylib               0x00b71d10 mono_sigill_signal_handler + 48 (mini-runtime.c:2377)
    9   libmono-2.0.dylib               0x00c20515 mono_find_jit_info_ext + 245 (mini-exceptions.c:391)
    10  libmono-2.0.dylib               0x00c20c9b mono_walk_stack_full + 299 (mini-exceptions.c:835)
    11  libmono-2.0.dylib               0x00c1fc08 mono_walk_stack_with_state + 216 (mini-exceptions.c:777)
    12  libmono-2.0.dylib               0x00c46436 debugger_interrupt_critical + 294 (debugger-agent.c:2583)
    13  libmono-2.0.dylib               0x00d8b5f4 mono_thread_info_safe_suspend_and_run + 148 (mono-threads.c:890)
    14  libmono-2.0.dylib               0x00c46268 notify_thread + 104 (debugger-agent.c:2671)
    15  libmono-2.0.dylib               0x00d36c52 mono_g_hash_table_foreach + 114 (mono-hash.c:283)
    16  libmono-2.0.dylib               0x00c45ee6 suspend_vm + 118 (debugger-agent.c:2753)
    17  libmono-2.0.dylib               0x00c4c20f debugger_thread + 15199 (debugger-agent.c:6869)
    18  libmono-2.0.dylib               0x00d8e140 inner_start_thread + 240 (mono-threads-posix.c:97)
    19  libmono-2.0.dylib               0x00db38bd GC_start_routine + 93 (pthread_support.c:1502)
    20  libsystem_pthread.dylib         0x9db38794 _pthread_body + 138
    21  libsystem_pthread.dylib         0x9db3870a _pthread_start + 155
    22  libsystem_pthread.dylib         0x9db35fa6 thread_start + 34
    
  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    So that's a crash in the middle of garbage collection I believe.

    Could you post your example cleaned and zipped up for us to look at?

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    As a side note, keeping the Application Output tab open during debugging of any Xamarin.Mac (or Xamarin.iOS) application is recommended. Apple will often print angry red text when you are "doing it wrong" with their APIs.

  • philstopfordphilstopford USMember
    edited October 2015

    For some reason, I got the impression that this would work as-is. Not sure why, but separating them out seems to be crash-free. Is there something that could be done to avoid the crash (I couldn't catch it with Try/Catch) in the runtime?

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    The following may be useful to read:

    http://developer.xamarin.com/guides/mac/application_fundamentals/troubleshooting/

    But in general, NSExceptions (which I think this might be) are not recoverable in general. Since they throw right past the managed/native barrier, it can leave your application in an "interesting" state if you hit those cases. Try/Catch only handles managed exceptions. And in some cases, if you hit an error case in Cocoa they just flat out kill your process.

Sign In or Register to comment.