1

I'm writing an alarm clock app, with a special twist to it. Not going to get into detail. Anyways, I'm trying to think of the best way to save the alarms.

I figured, since its a pretty basic app, it wouldn't require core data. So I was going to save them under NSUserDefaults. I used NSCoding to encode the objects, but I can't for the life of me figure out which key to use when saving them. Originally, I was going to use a key for each one. But that would involve searching NSUserDefaults keys for any that start with x (memory heavy). Also I'd have to find an efficient method to increment the key and circle back around when a key is deleted.

So then I tried adding the alarms to a dictionary (I tried an array, too) and adding THAT object to NSUserDefaults. To no avail.

Can somebody help me figure out the best way to do this? If it has to be core data, so be it. I just figured it was overkill for something as simple as adding alarm instances. Shooting for user defaults.

bad_coder
  • 11,289
  • 20
  • 44
  • 72
Katushai
  • 1,510
  • 2
  • 14
  • 27

1 Answers1

2

What about creating a custom class AllAlarms where it will save each alarm in a NSDictionary and then saves it in the NSUserDefaults under one key. Then you can create class method which returns array of all alarms from NSUserDefauls when you need it. This way you can search the array which will be much faster. Here is a code excerpt that shows this idea. It is from CS193P from last year. Let me know if you want to know the exact video where it was discussed. The only thing you have to make sure that everything you are storing in the NSDictionary are pLists. Hope this helps.

@property (nonatomic, strong) NSString *start;
@property (nonatomic, strong) NSString *end;


-(id)init
{
    //Do not call your setters and getters in the  designated initializer function of a class. Use instance variable to set the value. 

    self = [super self];
    if(self){
        _start = [NSDate date]; // returns date now
        _end = _start;
    }
    return self;
}



-(NSTimeInterval) duration
{
    //To return the different between dates you can use timeIntervalSinceDate: method
    return [self.end timeIntervalSinceDate:self.start];
}

//Writing out custom class to NSUserDefaults

#define START_KEY @"StartDate"
#define END_KEY @"EndDate"
#define SCORE_KEY @"Score"
#define ALL_RESULTS_KEY @"GameResult_All"

-(void)synchronize
{
    NSMutableDictionary *mutableGameResults = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:ALL_RESULTS_KEY]mutableCopy];  //get a mutable copy because NSUserDefaults are not mutable
    if(!mutableGameResults) mutableGameResults = [[NSMutableDictionary alloc]init];
    mutableGameResults[[self.start description]] = [self asPropertyList];
    [[NSUserDefaults standardUserDefaults]setObject:mutableGameResults forKey:ALL_RESULTS_KEY];
    [[NSUserDefaults standardUserDefaults] syncronize];

}

-(id)initFromPropertyList:(id)pList
{
    //convenience initializer
    self = [self init];
    if(self){
        if([pList isKindOfClass:[NSDictionary class]]){
            NSDictionary *resultDictionary = (NSDictionary *)pList
            _start = resultDictionary[START_KEY];
            _end = resultDictionary[END_KEY];
            _score = [resultDictionary[SCORE_KEY] intValue];
            if(!_start || !_end) self = nil;
        }
    }
    return self;
}


-(id)asPropertyList
{
    //returns a dictionaryof all the properties
    return @{START_KEY : self.start, END_KEY : self.end, SCORE_KEY : @(self.score)};
}

+(NSArray) allGameResults
{
    // returns all game results that are stored in NSUserDefaults in an Array
    NSMutableArray *allGameResults = [[NSMutableArray alloc]init];

    for(id plist in [[[NSUserDefaults standardUserDefaults] dictionaryForKey:ALL_RESULTS_KEY] allValues]){
        GameResult *result = [[GameResult alloc] initFromPropertyList:pList]; // using convenience initilazer to create game results from NSUserDefaults
        [allGameResults addObject:result];
    }
    return allGameResults;
}
Yan
  • 3,533
  • 4
  • 24
  • 45
  • good idea. that's what ill do. the data in the NSDictionary is a bunch of strings. thanks for the answer. i just wanted to make sure this was the correct method, in an attempt to lower overhead/memory usage – Katushai May 18 '14 at 03:52
  • I don't think there should be any issues with memory usage if you storing only strings. I am not sure but i don't see people storing 100s of alarms at the same time :) Happy Coding! – Yan May 18 '14 at 03:54
  • how do i save multiple instances to a dictionary without using a unique key? is there a way to do that? – Katushai May 18 '14 at 04:01
  • With this solution you are creating a dictionary of dictionaries and save it under one key in NSUserDefaults and then when u need to get all the alarms you can retrieve them once as an array of dictionaries and then you can search through them if you need to. – Yan May 18 '14 at 04:06
  • This way you can retrieve all alarms info once when app opens and then you can search through them or do whatever you need to do for your app – Yan May 18 '14 at 04:08
  • 1
    just did some reading. NSArray is what i should be using instead of NSDictionary. thanks for the help – Katushai May 18 '14 at 04:58