views:

131

answers:

1

Yet another iPhone/Objective-C noob question. I'm using a singleton to store app state information. I'm including the singleton in a Utilities class that holds it (and eventually other stuff). This utilities class is in turn included and used from various view controllers, etc. The utilities class is set up like this:

// Utilities.h
#import <Foundation/Foundation.h>

@interface Utilities : NSObject {

}

+ (id)GetAppState;
- (id)GetAppDelegate;

@end

// Utilities.m
#import "Utilities.h"
#import "CHAPPAppDelegate.h"
#import "AppState.h"

@implementation Utilities

CHAPPAppDelegate* GetAppDelegate() {
    return (CHAPPAppDelegate *)[UIApplication sharedApplication].delegate;
}

AppState* GetAppState() {
    return [GetAppDelegate() appState];
}

@end

... and the AppState singleton looks like this:

// AppState.h
#import <Foundation/Foundation.h>
@interface AppState : NSObject {
    NSMutableDictionary *challenge;
    NSString  *challengeID;
}
@property (nonatomic, retain) NSMutableDictionary *challenge;
@property (nonatomic, retain) NSString *challengeID;
+ (id)appState;
@end

// AppState.m
#import "AppState.h"

static AppState *neoAppState = nil;

@implementation AppState
@synthesize challengeID;
@synthesize challenge;

# pragma mark Singleton methods
+ (id)appState {
    @synchronized(self) {
        if (neoAppState == nil)
            [[self alloc] init];
    }
    return neoAppState;
}

+ (id)allocWithZone:(NSZone *)zone {
    @synchronized(self) {
        if (neoAppState == nil) {
            neoAppState = [super allocWithZone:zone];
            return neoAppState;
        }
    }
    return nil;
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

- (id)retain {
    return self;
}

- (unsigned)retainCount {
    return UINT_MAX; //denotes an object that cannot be released
}

- (void)release {
    // never release
}

- (id)init {
    if (self = [super init]) {
        challengeID = [[NSString alloc] initWithString:@"0"];
        challenge = [NSMutableDictionary dictionary];
    }
    return self;
}

- (void)dealloc {
    // should never be called, but just here for clarity
    [super dealloc];
}
@end

... then, from a view controller I'm able to set the singleton's "challengeID" property like this:

[GetAppState() setValue:@"wassup" forKey:@"challengeID"];

... but when I try to set one of the "challenge" dictionary entry values like this:

[[GetAppState() challenge] setObject:@"wassup" forKey:@"wassup"];

... it fails giving me an "unrecognized selector sent..." error. I'm probably doing something really obviously dumb? Any insights/suggestions will be appreciated.

+2  A: 

In your -init method, you should assign a retained dictionary to the ivar:

challenge = [[NSMutableDictionary alloc] init];
Georg Fritzsche
wow... such a little thing... so much banging of my head against the wall. THANK YOU! Marking this as answer as soon as system allows.
codemonkey
The magic principle of the second set of eyes i guess :)
Georg Fritzsche
oh... and I checked out your blog warning about singletons. i believe i'm still going to use this one, but i'll consider myself warned. thanks again.
codemonkey
... in this case it's more than it being a second set of eyes though... ur eyes actually understand what they're looking at... mine, still not so much in objective-c.
codemonkey