Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

mrtnbroder

macrumors newbie
Original poster
Sep 18, 2013
7
0
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:

ujo9.png


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).

t0n7.png


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!
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
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...
 

mrtnbroder

macrumors newbie
Original poster
Sep 18, 2013
7
0
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...

I don't want to use UserDefaults.

I want to save the preferences to a file.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
I don't want to use UserDefaults.

I want to save the preferences to a file.

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.
 

mrtnbroder

macrumors newbie
Original poster
Sep 18, 2013
7
0
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.

Okay. Then I'll use NSUserDefaults.

still - how to I accomplish settings different options per user?
 

mrtnbroder

macrumors newbie
Original poster
Sep 18, 2013
7
0
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 :)

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)
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
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)

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.
 

mrtnbroder

macrumors newbie
Original poster
Sep 18, 2013
7
0
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.

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
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.