Ele*_*que 0 exc-bad-access nsuserdefaults
这是许多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;
Run Code Online (Sandbox Code Playgroud)
}
在Box的encodeWithCoder方法中,它为它的所有数组创建了sereval NSData*对象,就像这样.
NSData* p1archv = [NSKeyedArchiver archivedDataWithRootObject:phase1];
[aCoder encodeObject:p1archv forKey:@"phase1"];
Run Code Online (Sandbox Code Playgroud)
它加载如下所有内容: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");
}
Run Code Online (Sandbox Code Playgroud)
它保存自己的盒子名称,如下所示:[aCoder encodeObject:boxName forKey:@"boxName"]; 加载是这样的:
boxName = [aDecoder decodeObjectForKey:@"boxName"];
Run Code Online (Sandbox Code Playgroud)
flashcards encodeWithCoder:
- (void) encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:question forKey:@"question"];
[aCoder encodeObject:answer forKey:@"answer"];
NSLog(@"encoded %@ and %@",question, answer);
Run Code Online (Sandbox Code Playgroud)
}
和initWithCoder:
- (id) initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
// Initialization code here.
question = [aDecoder decodeObjectForKey:@"question"];
answer = [aDecoder decodeObjectForKey:@"answer"];
}
return self;
Run Code Online (Sandbox Code Playgroud)
}
好的,现在您知道了实际设置,但这就是我的实际问题:
如果应用程序启动,并且有要加载的首选项,它将在Box.h文件中崩溃.确切地说,它崩溃在这一行:
@property (readwrite, copy) NSString* boxName;
Run Code Online (Sandbox Code Playgroud)
使用EXC_BAD_ACCESS.我打开NSZombieEnabled并显示完全相同的一行.在我的研究中,我在每一种方法都做了制动点,我发现,在使用Box的编码器方法的init中,一切正常,boxName就是它应该是什么(例如"foo")但是如果是tableview(Managed)通过NSArrayController)想要将数据加载到它在运行时崩溃的表视图中,或者在单步执行时显示诸如"1:918"之类的东西.我确定,我没有在加载过程中发布数组,或者boxName或其他任何东西,所以我无法解释这个问题.如果能帮助我,Elefantosque,我会很高兴的
我怀疑你的问题是decodeObjectForKey将始终返回一个自动释放的对象.因此:
boxName = [aDecoder decodeObjectForKey:@"boxName"]; // AUTORELEASED!!!
Run Code Online (Sandbox Code Playgroud)
将一个字符串粘贴到boxName中,最终会消失,然后你就会得到一个难看的东西.此外,被定义为此属性:
@property (readwrite, copy) NSString* boxName;
Run Code Online (Sandbox Code Playgroud)
当我使用时:
@property (readwrite, retain) NSString* boxName;
Run Code Online (Sandbox Code Playgroud)
然后在代码中使用以下内容:
self.boxName = [aDecoder decodeObjectForKey:@"boxName"]; // HAVE TO USE self.boxName
Run Code Online (Sandbox Code Playgroud)
这样做是将字符串保留在boxName中.我的猜测是,如果您更改属性行和分配行,您的错误将消失(尽管您可能有其他人).
如果您不想更改属性行,则可以使用:
[boxName autorelease]; // to be on the safe side
boxName = [[aDecoder decodeObjectForKey:@"boxName"] retain]; // no more uglygram
Run Code Online (Sandbox Code Playgroud)
规则:除非你使用[alloc],否则假设该对象是自动释放的.
| 归档时间: |
|
| 查看次数: |
1535 次 |
| 最近记录: |