这是许多EXC_BADACCES问题之一,但我已经做了很长时间的研究,并认为这个问题尚未得到解答。我的应用程序在首选项中保存数据。一切都很好,如果我删除首选项并启动应用程序,那么根本不会发生任何加载。但如果发生加载,就会出现问题。我必须保存一个主数组,其中包含一个名为Box的自写对象。 One 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");
}
它保存自己的盒子名称,如下所示: [aCoder encodeObject:boxName forKey:@“boxName”]; 加载是这样的:
boxName = [aDecoder decodeObjectForKey:@"boxName"];
flashcards encodeWithCoder:
- (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”)但是如果是tableview(Managed)通过NSArrayController)想要将数据加载到表视图中,它在运行时崩溃或显示像例如单步执行“1:918”。我确定,我没有在加载过程中发布数组,或者boxName或其他任何东西,所以我无法解释这个问题。如果你能帮助我,我会很高兴,Elefantosque
答案 0 :(得分:6)
我怀疑你的问题是decodeObjectForKey将始终返回一个自动释放的对象。因此:
boxName = [aDecoder decodeObjectForKey:@"boxName"]; // AUTORELEASED!!!
将一个字符串粘贴到boxName中,最终会消失,然后你会得到一个难看的东西。另外,被定义为这个属性:
@property (readwrite, copy) NSString* boxName;
当我使用时:
@property (readwrite, retain) NSString* boxName;
然后在代码中使用以下内容:
self.boxName = [aDecoder decodeObjectForKey:@"boxName"]; // HAVE TO USE self.boxName
这样做是将字符串保留在boxName中。我的猜测是,如果您更改属性行和分配行,您的错误将消失(尽管您可能有其他人)。
如果您不想更改属性行,则可以使用:
[boxName autorelease]; // to be on the safe side
boxName = [[aDecoder decodeObjectForKey:@"boxName"] retain]; // no more uglygram
THUMB规则:除非你使用[alloc],否则假定该对象是自动释放的。