在@Property上加载首选项时应用程序崩溃(EXC_BAD_ACCESS)



这是EXC_BADACCES的许多问题之一,但我做了很长时间的研究,认为这个问题还没有得到回答。我的应用程序将数据保存在首选项中。如果我删除首选项并启动应用程序,一切都很顺利,这样就不会发生加载。但如果发生装载,就会出现问题。我必须保存一个主数组,该数组包含名为Box的自写对象。一个盒子有一个NSString*boxName,六个NSMutableArray*包含另一个自写对象,名为Flashcard,包含两个NSString*:问题和答案。如果AppDelegate获得消息applicationWillTerminate,它将使用NSKeyedArchiver对主数组(称为boxArray)进行编码,并将其保存在首选项中。在AppControll的init方法中,这个档案是从首选项加载的:

- (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;

}

在Box的encodeWithCoder方法中,它为所有数组创建sereval NSData*对象,如下所示。

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

它加载的内容如下: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");
    }

它保存自己的框名如下:[aCode-encodeObject:boxName for Key:@"boxName"];加载是这样的:

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

闪存卡编码器WithCoder:

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

}

和initWithCoder:

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

}

好的,现在你知道实际设置了,但这就是我的实际问题:

如果应用程序启动,并且有要加载的首选项,它就会在Box.h文件中崩溃。确切地说,它在这一行崩溃:

@property (readwrite, copy) NSString* boxName;

具有EXC_BAD_ACCESS。我打开NSZombieEnabled,它显示完全相同的行。在我的研究中,我对每一个方法都提出了制动点,我发现,在Box的编码器方法的init中,一切都很好,boxName就是它应该是的(例如"foo"),但如果表视图(由NSArrayController管理)想将数据加载到表视图中,它在运行时会崩溃,或者在单步执行中显示出类似"1:918"的内容。我确信,我之前在加载过程中没有发布数组、boxName或任何东西,所以我无法解释这个问题。如果你能帮助我,我将非常高兴,Elefantosque

我怀疑您的问题是decodeObjectForKey将始终返回一个自动释放的对象。因此:

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

在boxName中粘贴一个字符串,它最终会消失,然后你会得到一个丑陋的gram。同样,定义为以下属性:

@property (readwrite, copy) NSString* boxName;

当我会使用:

@property (readwrite, retain) NSString* boxName;

然后在代码中使用以下内容:

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

这样做的目的是将字符串保留在boxName中。我的猜测是,如果你更改了属性行和赋值行,你的bug就会消失(尽管你可能还有其他bug)。

如果你不想改变你的财产线,那么你可以使用:

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

THUMB规则:除非使用[alloc],否则假设对象是自动释放的。

最新更新