Question

I have been trying for quite a while to find a solution to a problem which ought to be pretty straight forward. What I want is variables that can be edited in the iPhone settings menu while the app is not running. Basically a config file wrapped in the iOS GUI.

This is supposed to be an built-in feature in iOS, and while I can find some methods related to it, I can't find an actual solution.

The closest I've been to getting what I want is where it works like any other variable: Empty on application start, and gets scratched again on application close. And still not visible in the iPhone Settings window.

This is the code I have:

private void LoadSettingsFromIOS()
{
    // This is where it works like any other variable. Aka. gets scratched on app closing.
    _thisUser.SetValueForKey(new NSString("Blargh"), new NSString("SaveCredentials"));
    string stringForKey = _thisUser.StringForKey("SaveCredentials");

    // This is where I'm supposed to be able to load the data from settings and set the checkbox's 'On' state to the value. Currently it always returns False.
    bool saveCredentials = _thisUser.BoolForKey("SaveCredentials");
    chckBoxRememberMe.On = saveCredentials;
}

And my Settings.Bundle Root.pList file:

  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  <plist version="1.0">
  <dict>
      <key>PreferenceSpecifiers</key>
      <array>
          <dict>
              <key>Type</key>
              <string>PSToggleSwitchSpecifier</string>
              <key>Title</key>
              <string>Credentials</string>
              <key>Key</key>
              <string>SaveCredentials</string>
              <key>DefaultValue</key>
              <true/>
          </dict>
      </array>
      <key>StringsTable</key>
      <string>Root</string>
  </dict>
  </plist>

Anyone out there who's been messing with Xamarin iOS and knows how this works?

Was it helpful?

Solution

EDIT: Here is a working project in Xamarin: https://github.com/xamarin/monotouch-samples/tree/master/AppPrefs

First, you need to make your view visible in the iPhone Settings window.

To do that, you need to create a folder named "Settings.bundle" in the top-level directory of your app’s bundle. Then, create new file named "Root.plist". The file has to be of the type Property List. You do that by right-clicking Settings.bundle, then Add -> New File... -> iOS (on the left pane) -> Property List. If you add an empty file and then rename it as .plist, it won't show in iPhone's Settings.

The first element in your Root.plist has to be an Array, and it must contain Dictionaries.

You can find more info here on how to construct your Settings View: https://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/UserDefaults/Preferences/Preferences.html

Pay attention to Figure 4-2 (Strings Filename is not necessary). Also, edit the Root.plist file in the Xamarin editor, it is much easier.

To get values from the newly created Settings, you can use this class (Add as many properties as you want):

public class Settings
{
    public static string ApiPath { get; private set; }

    const string API_PATH_KEY = "serverAddress"; //this needs to be the Identifier of the field in the Root.plist

    public static void SetUpByPreferences()
    {
        var testVal = NSUserDefaults.StandardUserDefaults.StringForKey(API_PATH_KEY);

        if (testVal == null)
            LoadDefaultValues();
        else
            LoadEditedValues();

        SavePreferences();
    }

    static void LoadDefaultValues()
    {
        var settingsDict = new NSDictionary(NSBundle.MainBundle.PathForResource("Settings.bundle/Root.plist", null));

        if (settingsDict != null)
        {
            var prefSpecifierArray = settingsDict[(NSString)"PreferenceSpecifiers"] as NSArray;

            if (prefSpecifierArray != null)
            {
                foreach (var prefItem in NSArray.FromArray<NSDictionary>(prefSpecifierArray))
                {
                    var key = prefItem[(NSString)"Key"] as NSString;

                    if (key == null)
                        continue;

                    var value = prefItem[(NSString)"DefaultValue"];

                    if (value == null)
                        continue;

                    switch (key.ToString())
                    {
                        case API_PATH_KEY:
                            ApiPath = value.ToString();
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    }

    static void LoadEditedValues()
    {
        ApiPath = NSUserDefaults.StandardUserDefaults.StringForKey(API_PATH_KEY);
    }

    //Save new preferences to Settings
    static void SavePreferences()
    {
        var appDefaults = NSDictionary.FromObjectsAndKeys(new object[] {
            new NSString(ApiPath)
        }, new object[] {
            API_PATH_KEY
        });

        NSUserDefaults.StandardUserDefaults.RegisterDefaults(appDefaults);
        NSUserDefaults.StandardUserDefaults.Synchronize();
    }
}

You just call SetUpByPreferences() (which is the only public method), and then get the values from the properties in the class.

OTHER TIPS

Try this:

NSBundle.MainBundle.PathForResource ("Settings", @"bundle");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top