views:

116

answers:

2

I have spent hours trying to get my project working and I just can't get it working.

Basically, I'm trying to use NSUserDefaults to save a custom object when the user hits a save button and load all the data up when the app loads. If there is no previous NSUserDefault saved, I want to set some defaults. In the end, I am getting EXC_BAD_ACCESS when trying to load a previously-saved NSUserDefault. It works fine the first load, when setting the starting data. And the thing is, when I try to enable NSZombieEnabled and the other env vars for it, it somehow loads fine without the EXC_BAD_ACCESS. So here's what I'm working with:

[App Delegate.h]

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

@interface ToDoWallAppDelegate : NSObject <UIApplicationDelegate> {
    ...
    Note *note;
}

...
@property (retain) Note *note;

@end

[App Delegate.m]

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    ...
    note = [[Note alloc] init];

    NSUserDefaults *stdDefaults = [NSUserDefaults standardUserDefaults];
    NSData *noteData = [stdDefaults objectForKey:@"Note"];
    if (noteData) {
        self.note = (Note *)[NSKeyedUnarchiver unarchiveObjectWithData:noteData];
    } else {
        note.background = [UIImage imageNamed:@"Cork.jpg"];
        note.picture = [UIImage imageNamed:@"Cork.jpg"];
        note.font = [UIFont fontWithName:@"Helvetica" size:18.0f];
        note.fontColor = [UIColor blackColor];
        note.fontNameIndex = 9;
        note.fontSizeIndex = 6;
        note.fontColorIndex = 0;
        note.backgroundIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
        note.pictureIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
        note.text = @"Type note here...";
    }

    ...
}

- (void)dealloc {
    ...
    [note release];
    [super dealloc];
}

[View Controller]

- (void)saveNote {
    ...
    NSUserDefaults *stdDefaults = [NSUserDefaults standardUserDefaults];
    if (stdDefaults) {
        NSData *noteData = [NSKeyedArchiver archivedDataWithRootObject:UIAppDelegate.note];
        [stdDefaults setObject:noteData forKey:@"Note"];
        [stdDefaults synchronize];
    }
}

[Note.h]

#import <Foundation/Foundation.h>


@interface Note : NSObject <NSCoding> {
    UIImage *background, *picture;
    UIFont *font;
    UIColor *fontColor;
    int fontNameIndex, fontSizeIndex, fontColorIndex;
    NSIndexPath *backgroundIndexPath, *pictureIndexPath;
    BOOL customBackground;
    NSString *text;
}

@property (retain) UIImage *background, *picture;
@property (retain) UIFont *font;
@property (retain) UIColor *fontColor;
@property int fontNameIndex, fontSizeIndex, fontColorIndex;
@property (retain) NSIndexPath *backgroundIndexPath, *pictureIndexPath;
@property BOOL customBackground;
@property (retain) NSString *text;

- (Note *)init;

@end

[Note.m]

#import "Note.h"


@implementation Note

@synthesize background, picture, font, fontColor, fontNameIndex, fontSizeIndex, fontColorIndex, customBackground, backgroundIndexPath, pictureIndexPath, text;

- (Note *)init {
    if (self = [super init]) {
        background = [[UIImage alloc] init];
        picture = [[UIImage alloc] init];
        font = [[UIFont alloc] init];
        fontColor = [[UIColor alloc] init];
        backgroundIndexPath = [[NSIndexPath alloc] init];
        pictureIndexPath = [[NSIndexPath alloc] init];
        text = [[NSString alloc] init];
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder {
    NSData *dataBackground = UIImagePNGRepresentation(background);
    NSData *dataPicture = UIImagePNGRepresentation(picture);

    [encoder encodeObject:dataBackground forKey:@"dataBackground"];
    [encoder encodeObject:dataPicture forKey:@"dataPicture"];
    [encoder encodeObject:font forKey:@"font"];
    [encoder encodeObject:fontColor forKey:@"fontColor"];
    [encoder encodeInt:fontSizeIndex forKey:@"fontSizeIndex"];
    [encoder encodeInt:fontColorIndex forKey:@"fontColorIndex"];
    [encoder encodeBool:customBackground forKey:@"customBackground"];
    [encoder encodeObject:backgroundIndexPath forKey:@"backgroundIndexPath"];
    [encoder encodeObject:pictureIndexPath forKey:@"pictureIndexPath"];
    [encoder encodeObject:text forKey:@"text"];
}

- (Note *)initWithCoder:(NSCoder *)decoder {
    if (self = [super init]) {
        NSData *dataBackground = [decoder decodeObjectForKey:@"dataBackground"];
        NSData *dataPicture = [decoder decodeObjectForKey:@"dataPicture"];
        background = [[UIImage imageWithData:dataBackground] retain];
        picture = [[UIImage imageWithData:dataPicture] retain];
        font = [[decoder decodeObjectForKey:@"font"] retain];
        fontColor = [[decoder decodeObjectForKey:@"fontColor"] retain];
        fontNameIndex = [decoder decodeIntForKey:@"fontNameIndex"];
        fontColorIndex = [decoder decodeIntForKey:@"fontColorIndex"];
        customBackground = [decoder decodeBoolForKey:@"customBackground"];


    backgroundIndexPath = [[decoder decodeObjectForKey:@"backgroundIndexPath"] retain];
        text = [[decoder decodeObjectForKey:@"text"] retain];
    }
    return self;
}

- (void)dealloc {
    [super dealloc];
    [background release];
    [picture release];
    [font release];
    [fontColor release];
    [backgroundIndexPath release];
    [pictureIndexPath release];
    [text release];
}

@end

I really need some help I appreciate it.

Edit:

Btw, there are also lines from other files that edit the App Delegate's Note object, such as:

#define UIAppDelegate ((ToDoWallAppDelegate *)[UIApplication sharedApplication].delegate)
...
UIAppDelegate.note.backgroundIndexPath = indexPath;

Edit:

This is what debugger wrote:

#0  0x90be9ed7 in objc_msgSend
#1  0x03b05210 in ??
#2  0x000023ce in -[ToDoWallAppDelegate setNote:] at ToDoWallAppDelegate.m:14
#3  0x00002216 in -[ToDoWallAppDelegate applicationDidFinishLaunching:] at ToDoWallAppDelegate.m:35

Which are:

note.text = @"Type note here...";
//and
@synthesize window, note;
A: 

Have a look at documentation how to setup defaults Using NSUserDefaults

If you need more info have a look in Hillega's book "Cocoa programming for Mac OS X" bignerdranch.com/books, it's explained there.

You should consider changing the headline to "How to use NSUserDefaults" ...

Example how to setup default value, in your class in initialize put something like:

+ (void)initialize{

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSDictionary *appDefaults = [NSDictionary
        dictionaryWithObject:@"YES" forKey:@"DeleteBackup"];

    [defaults registerDefaults:appDefaults];
}

You could post where exactly are you getting the error instead of posting the whole code. Run it through debugger and see where it stops.

stefanB
Oh, never knew about debugger. Edited main post to show what debugger wrote.
Kurbz
+5  A: 

I'm not sure if this is what's causing your problem, but I believe that [super dealloc] should be the LAST line of your dealloc method, not the first.

Mitch Lindgren
THANK YOU! Turns out that was it all along, I would've never looked there.
Kurbz
Glad to be of help :)
Mitch Lindgren
By the way, since you found this answer helpful, you can hit "Accept" to mark it as correct for the benefit of other users.
Mitch Lindgren