views:

230

answers:

1

Hi Everyone.

I'm making an app where I need to save the text in multiple views in the app when the app quits. I also need to be able to remove all of the data from just one of those views and when the app quits, it's possible not all of those views will have been created yet.

After reading this post I thought perhaps it would be good to use a singleton that manages my app data which loads in the data when it is first requested and saved it when the app quits. Then in each view where I need to save data I can just set it on the singleton.

I gave it a go but have run into some issues. At first I didn't synthesize the properties (as in the post I was using as a guide) but the compiler told me I needed to make getters and setters, so I did. Now when my applicationWIllTerminate: gets call the app crashes and the console says "Program received signal: “EXC_BAD_ACCESS”. kill quit".

Is anyone able to tell me what I'm doing wrong, or suggest a better approach to saving the data?

//SavedData.h

#import <Foundation/Foundation.h>

#define kFileName @"appData.plist"

@interface SavedData : NSObject {
    NSString *information;
    NSString *name;
    NSString *email;
    NSString *phone;
    NSString *mobile;
}

@property(assign) NSString *information;
@property(assign) NSString *name;
@property(assign) NSString *email;
@property(assign) NSString *phone;
@property(assign) NSString *mobile;

+ (SavedData *)singleton;

+ (NSString *)dataFilePath;
+ (void)applicationWillTerminate:(NSNotification *)notification;
@end

//SavedData.m

#import "SavedData.h"

@implementation SavedData

@synthesize information;
@synthesize name;
@synthesize email;
@synthesize phone;
@synthesize mobile;

static SavedData * SavedData_Singleton = nil;

+ (SavedData *)singleton{

    if (nil == SavedData_Singleton){
        SavedData_Singleton = [[SavedData_Singleton alloc] init];

        NSString *filePath = [self dataFilePath];
        if([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
            NSMutableArray * array = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
            information = [array objectAtIndex:0];
            name = [array objectAtIndex:1];
            email = [array objectAtIndex:2];
            phone = [array objectAtIndex:3];
            mobile = [array objectAtIndex:4];           
            [array release];
        }
        UIApplication *app = [UIApplication sharedApplication];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:app]; 
    }
    return SavedData_Singleton;
}

+ (NSString *)dataFilePath{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *DocumentsDirectory = [paths objectAtIndex:0];
    return [DocumentsDirectory stringByAppendingPathComponent:kFileName];
}

+ (void)applicationWillTerminate:(NSNotification *)notification{
    NSLog(@"Application will terminate received");
    NSMutableArray *array = [[NSMutableArray alloc] init];
    [array addObject:information];
    [array addObject:name];
    [array addObject:email];
    [array addObject:phone];
    [array addObject:mobile];
    [array writeToFile:[self dataFilePath] atomically:YES];
    [array release];
}

@end

Then when I want to use it I do

myLabel.text = [SavedData singleton].information;

And when I change the field

[SavedData singleton].information = @"my string";

Any help will be very much appreciated!

+1  A: 

You might want to change your properties to be (retain) instead of assign.

You might want to get the singleton header file I use. It is quite nice for me.

What is likely happening is that you load up your array from a file, and assign it to the property. But it is being autoreleased, and thus it doesn't exist anymore. So when you try to access the memory later, it crashes.

Further reading on memory management: http://www.cocoadev.com/index.pl?MemoryManagement

iaefai
+1 Yes, the assigns instead of retains are almost certainly the problem. It's highly unlikely that the assigned objects hang around for the entire life of the application.
TechZen
Thanks for that link. That is great but it would be awesome if you could show some sample code of it in use as I'm still not sure now where I put the code that I want to execute when the singleton is first created. Do I need to make an implimentation of +(MyClassName *)sharedMyClassName; or is that what the macro is doing?
DownUnder