开发者

App Crashes (EXC_BAD_ACCESS) while loading Preferences on @Property

this is one of many EXC_BADACCES questions, but I have done research for a long time and think that this question has not been answered yet. My App saves data with in the preferences. Everything wents well, if I delete the preferences und start the App, so that no loading happens at all. But if loading happens, there is a problem. I have to save one main array wich contains self-written objects called Box. One Box has a NSString* boxName and six NSMutableArray* wich contain another self written object, called Flashcard wich contains two NSString*: question and answer. If the AppDelegate gets the message applicationWillTerminate it encodes the main array (called boxArray) using the NSKeyedArchiver and saves it in the preferences. In the init method of AppControll, this archive is loaded from the preferences:

- (id)init {
self = [super init];
if (self) {
    // Initialization code here.
    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    NSData* archive = [defaults objectForKey:@"boxArray"];
    if (archive) {
        NSArray* array = [NSKeyedUnarchiver unarchiveObjectWithData:archive];
        boxArray = [NSMutableArray arrayWithArray:array];
    } else {
    boxArray = [[NSMutableArray alloc] init];
    }

}

return self;

}

In the encodeWithCoder method of Box, it creates sereval NSData* objects for all its arrays, like this.

NSData* p1archv = [NSKeyedArchiver archivedDataWithRootObject:phase1];  
[aCoder encodeObject:p1archv forKey:@"phase1"];

and it loads everything like this: NSData* p1archv = [aDecoder decodeObjectForKey:@"phase1"];

if (p1archv) {
        NSArray* a = [NSKeyedUnarchiver unarchiveObjectWithData:p1archv];
        phase1 = [NSMutableArray arrayWithArray:a];
        NSLog(@"loaded phase1: %@",phase1);
    } else {
        phase1 = [[NSMutableArray alloc] init];
        NSLog(@"inited phase1");
    }

It saves its own box name like this: [aCoder encodeObject:boxName forKey:@"boxName"]; Loading is like this:

 boxName = [aDecoder decodeObjectForKey:@"boxName"];

The flashcards encodeWithCoder:

- (void) encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:question forKey:@"question"];
[aCoder encodeObject:answer forKey:@"answer"];
NSLog(@"encoded %@ and %@",question, answer);

}

开发者_运维百科and initWithCoder:

- (id) initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
    // Initialization code here.
    question = [aDecoder decodeObjectForKey:@"question"];
    answer = [aDecoder decodeObjectForKey:@"answer"];
}

return self;

}

Ok, now you know the actual setting, but this is what my actual problem is:

If the application starts, and there are preferences to load, it crashes in the Box.h file. To be exact it crashes in this line:

@property (readwrite, copy) NSString* boxName;

with an EXC_BAD_ACCESS. I turned NSZombieEnabled on and it showed exactly the same line. On my research I made brake-points at every single method, and I found out, that in the init with coder method of Box, everything is ok and boxName is what it should be (e.g. "foo") but if the tableview (Managed by an NSArrayController) wants to load the data into the table view it crashes in the while running or it´s showing stuff like e.g. "1:918" in stepping through the single steps. I#m sure, I have not released the array, or the boxName or anything before in the loading process, so I can´t explain this issue. I would be very glad if you could help me, Elefantosque


I suspect your problem is the fact that decodeObjectForKey will always return an autoreleased object. Therefore:

boxName = [aDecoder decodeObjectForKey:@"boxName"]; // AUTORELEASED!!!

Sticks a string into boxName that will eventually disappear and then you get an ugly-gram. ALSO, is defined as this property:

@property (readwrite, copy) NSString* boxName;

When I would have used:

@property (readwrite, retain) NSString* boxName;

And then in the code used the following:

self.boxName = [aDecoder decodeObjectForKey:@"boxName"]; // HAVE TO USE self.boxName

What THAT does is retain the string in boxName. My guess is that if you change the property line and the assignment line, your bug will disappear (although you may have others).

IF you don't want to change your property line, then you could use:

 [boxName autorelease];                                       // to be on the safe side
 boxName = [[aDecoder decodeObjectForKey:@"boxName"] retain]; // no more uglygram

RULE OF THUMB: Unless you use [alloc] assume that the object is autoreleased.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜