Selch
Selch

Reputation: 131

Can't add entry to NSMutableDictionary in singleton

I have a singleton with an NSMutableDictionary in it. I want to add an entry to that dictionary from one of my views. For a reason that I can't comprehend it's not working and I'm receiving the 'NSDictionary setObject:forKey: unrecognized selector sent to instance' error. This doesn't seem like it should be so hard but I can't find an answer to the problem.

So I've wired up a button in my .xib to call the createKey method and kablooey. I've also tested to ensure that the dictionary exists and it does.

Here's my singleton header:

#import <Foundation/Foundation.h>

@interface SharedAppData : NSObject <NSCoding>
{
    NSMutableDictionary *apiKeyDictionary;
}

+ (SharedAppData *)sharedStore;

@property (nonatomic, copy) NSMutableDictionary *apiKeyDictionary;

-(BOOL)saveChanges;

@end

My singleton implementation (important bits)

 @interface SharedAppData()
    @end

    @implementation SharedAppData

    @synthesize apiKeyDictionary;

    static SharedAppData *sharedStore = nil;

+(SharedAppData*)sharedStore {

        @synchronized(self){
        if(sharedStore == nil){
            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *documentsDirectory = [paths objectAtIndex:0];
            NSString *testFile = [documentsDirectory stringByAppendingPathComponent:@"testfile.sav"];
            Boolean fileExists = [[NSFileManager defaultManager] fileExistsAtPath:testFile];

            if(fileExists) {
                sharedStore = [NSKeyedUnarchiver unarchiveObjectWithFile:testFile];
            }
            else{
                sharedStore = [[super allocWithZone:NULL] init];
            }

            [sharedStore setSaveFile:testFile];
        }

            return sharedStore;
        }
}

    - (id)init {
        if (self = [super init]) {
            apiKeyDictionary = [[NSMutableDictionary alloc] init];      
        }
        return self;
    }

In my view controller header...

#import <UIKit/UIKit.h>
#import "SharedAppData.h"

@interface AddKeyViewController : UIViewController <UITextFieldDelegate>
{
    UIButton *addKey;
}

@property (weak, nonatomic) IBOutlet UITextField *apiName;
@property (weak, nonatomic) IBOutlet UITextField *apiKey;

-(IBAction)createKey:(id)sender;

@end

View controller implementation:

#import "AddKeyViewController.h"
#import "SharedAppData.h"

@interface AddKeyViewController ()

@end

@implementation AddKeyViewController

@synthesize apiName, apiKey, toolbar;

-(IBAction)createKey:(id)sender {

    NSString *name = [apiName text];
    NSString *key = [apiKey text];

    [[[SharedAppData sharedStore] apiKeyDictionary] setObject:key forKey:name];
}

@end

Upvotes: 2

Views: 673

Answers (2)

Carl Veazey
Carl Veazey

Reputation: 18363

Your apiKeyDictionary property is set to copy. That will send the copy message to the NSMutableDictionary instance you create in your init method - returning not an NSMutableDictionary but an NSDictionary. Change it to strong or retain instead.

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726809

I suspect that the problem is with your property being "copy" rather than "strong"; when you set it, mutanle dictionsry gets copied into an immutable one. Try changing your property to "strong".

Upvotes: 2

Related Questions