Save preferences and load them up on next start

Discussion in 'Mac Programming' started by mrtnbroder, Sep 18, 2013.

  1. macrumors newbie

    Joined:
    Sep 18, 2013
    #1
    Hello!

    I'm still a newbie at Objectice-C and I'm trying to achieve the following:

    At the very first time my Application starts, there are some default preferences settings which are getting set. Now, when the User the App closes, it saves all preferences into a file.
    Next time the User opens the App, the preferences get loaded from the file.

    Model: Preferences : NSObject
    View: PreferencesWindow (ist eine nib)
    Controller: PreferencesController : NSWindowController

    In my PreferencesWindow.nib lies an Object from the Class "Preferences", which references to my "Preferences"-Model.
    I've setup my bindings like this for example:

    [​IMG]

    My Model looks like this:

    Code:
    // Preferences.h
    
    @interface Preferences : NSObject
    {
        int         _irgendeinRadioMenuTag;
        int         _nochEinRadioMenuTag;
        NSString    *_username;
        NSString    *_password;
        BOOL        _shouldDoThis;
        BOOL        _shouldDoThat;
    }
    
    @property (nonatomic, assign)   int         irgendeinRadioMenuTag;
    @property (nonatomic, assign)   int         nochEinRadioMenuTag;
    @property (nonatomic, copy)     NSString    *username
    @property (nonatomic, copy)     NSString    *password;
    @property (nonatomic, assign)   BOOL        shouldDoThis;
    @property (nonatomic, assign)   BOOL        shouldDoThat;
    
    + (Preferences *) sharedPreferences;
    - (BOOL) loadDefaults;
    - (BOOL) saveDefaults;
    
    Code:
    //  Preferences.m
    
    #import "Preferences.h"
    
    @implementation Preferences
    
    @synthesize irgendeinRadioMenuTag       = _irgendeinRadioMenuTag;
    @synthesize nochEinRadioMenuTag         = _nochEinRadioMenuTag;
    @synthesize username                    = _username;
    @synthesize password                    = _password;
    @synthesize shouldDoThis                = _shouldDoThis;
    @synthesize shouldDoThat                = _shouldDoThat;
    
    
    + (Preferences *) sharedPreferences
    {
        static Preferences *_sharedPreferences = nil;
        static dispatch_once_t onceToken;
    
        dispatch_once(&onceToken, ^{
            _sharedPreferences = [[self alloc] init];
        });
    
        return _sharedPreferences;
    }
    
    
    - (id) init
    {
        self = [super init];
    
        if (self) {
    
        }
    
        return self;
    }
    
    
    - (BOOL) loadDefaults
    {
    
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *docDir = [paths objectAtIndex: 0];
        NSString *preferencesFile = [docDir stringByAppendingPathComponent: @"preferences.plist"];
    
        BOOL settingsExist = [[NSFileManager defaultManager] fileExistsAtPath:preferencesFile];
    
        if (settingsExist) {
            NSLog(@"Settings found!");
    
            NSMutableDictionary *defaultsDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:preferencesFile];
    
            _irgendeinRadioMenuTag  = (int)[[defaultsDictionary objectForKey:@"irgendeinRadioMenuTag"] integerValue];
            _nochEinRadioMenuTag    = (int)[[defaultsDictionary objectForKey:@"nochEinRadioMenuTag"] integerValue];
            _shouldDoThis           = [[defaultsDictionary objectForKey:@"shouldDoThis"] boolValue];
            _shouldDoThat           = [[defaultsDictionary objectForKey:@"shouldDoThat"] boolValue];
            _username               = [defaultsDictionary objectForKey:@"username"];
            _password               = [defaultsDictionary objectForKey:@"password"];
    
        }
    
        return settingsExist;
    
    }
    
    - (BOOL) saveDefaults
    {
    
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *docDir = [paths objectAtIndex: 0];
        NSString *preferencesFile = [docDir stringByAppendingPathComponent: @"preferences.plist"];
    
        NSMutableDictionary *defaultsDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:preferencesFile];
    
        [defaultsDictionary setObject:[NSNumber numberWithInt:_irgendeinRadioMenuTag] forKey:@"irgendeinRadioMenuTag"];
        [defaultsDictionary setObject:[NSNumber numberWithInt:_nochEinRadioMenuTag] forKey:@"nochEinRadioMenuTag"];
        [defaultsDictionary setObject:[NSNumber numberWithBool:_shouldDoThis] forKey:@"shouldDoThis"];
        [defaultsDictionary setObject:[NSNumber numberWithBool:_shouldDoThat] forKey:@"shouldDoThat"];
        [defaultsDictionary setObject:_username forKey:@"username"];
        [defaultsDictionary setObject:_password forKey:@"password"];
    
        if ([defaultsDictionary writeToFile:preferencesFile atomically:YES]) {
            NSLog(@"Successfully wrote Settings to %@", preferencesFile);
            return YES;
        } else {
            NSLog(@"Failed to write Settings to %@", preferencesFile);
            return NO;
        }
    
        return NO;
    }
    @end
    
    This is what happens upon starting the application:

    Code:
    - (void) applicationDidFinishLaunching:(NSNotification *)aNotification
    {
        // _preferenceWindow ist einfach eine instanz variable von PreferencesController
        if (_preferenceWindow == nil) {
            _preferenceWindow = [[PreferencesController alloc] initWithWindowNibName:@"Preferences"];
        }
        
        [_preferenceWindow loadDefaults]; // verweist im controller selbst einfach auf [[Preferences sharedPreferences] loadDefaults]
    }
    
    - (void) applicationWillTerminate:(NSNotification *)notification
    {
        [_preferenceWindow saveDefaults];
    }
    
    Now my questions:

    1. How do I set some default values? Can't I do that in the .nib/.xib?
    2. Do I have to create the preferences.plist file? Or does writeToFile does that automatically?
    3. Later on, there should be per-profile-preferences. like each user has it's on username and a different id or something (well I call it extraOption here now, just for the sake of it).

    [​IMG]

    Since when the App starts, the LAST logged in username will be filled into the appropiate TextField. How can I setup this?

    Thanks for your help!
     
  2. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    Why are you re-implementing NSUserDefaults? It even has a way for the application to register default values from a plist which user values then automatically override...
     
  3. thread starter macrumors newbie

    Joined:
    Sep 18, 2013
    #3
    I don't want to use UserDefaults.

    I want to save the preferences to a file.
     
  4. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4
    Why in particular? Users expect preferences to be saved to the correct directory in the correct format. NSUserDefaults does the automatically (not it does save to a file). NSUserDefaults also supports correctly supports managed environments (computer labs etc). Not using this may well make your application difficult or even impossible for computer administrators to install on larger networks.

    In general I'd recommend using the system provided architecture wherever possible. Re-implementing basics like this pretty much only ever leads to bugs.
     
  5. thread starter macrumors newbie

    Joined:
    Sep 18, 2013
    #5
    Okay. Then I'll use NSUserDefaults.

    still - how to I accomplish settings different options per user?
     
  6. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #6
    You don't: NSUserDefaults does this for you: it saves per user into the users directory. Pretty much every Cocoa app that has user preferences uses it :)
     
  7. thread starter macrumors newbie

    Joined:
    Sep 18, 2013
    #7
    No no no :) Thats now what I ment.

    I've got 2 fields on my app - username and password.

    now when I click login, it saves the username, password, an "extraOption" that has a unique value and all the other preferences to NSUserDefaults ( ;) )

    but now I click logout, because I want to login another account, which should have another "extraOption", which is different.

    (see screenshot above, and you'll see what I mean)
     
  8. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #8
    Ah, in that case you will probably need to use a more complex data structure. I'd save a NSDictionary which is keyed on the login ID. Each element of this dictionary would be another NSDictionary with keys for each option to save.
     
  9. thread starter macrumors newbie

    Joined:
    Sep 18, 2013
    #9
    thanks.

    how would my binding look like when I do that? current I bind to Shared User Defaults.values.username...

    but shounldn't it look more like:

    Shared User Defaults.values.users.%username%

    %username% = the actual username
     
  10. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #10
    Bindings will make it more complex. I suspect you may need a NSDictionaryController...
     

Share This Page