2011-05-29 106 views
0

这是许多EXC_BADACCES问题之一,但我已经做了很长时间的研究,并认为此问题尚未得到解答。我的应用程序将数据保存在首选项中。如果我删除首选项并启动应用程序,那么一切都很顺利,这样就不会发生任何加载。但是如果发生加载,就会出现问题。我必须保存一个主阵列,其中包含名为Box的自写对象。 One Box有一个NSString * boxName和六个NSMutableArray *,其中包含另一个自写对象,称为Flashcard,其中包含两个NSString *:问题和答案。如果AppDelegate获取消息applicationWillTerminate,则使用NSKeyedArchiver对主数组(称为boxArray)进行编码并将其保存在首选项中。在AppControll的init方法,该归档文件是从喜好加载:在@Property上加载首选项时,应用程序崩溃(EXC_BAD_ACCESS)

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

}

在盒子的encodeWithCoder方法,它创建sereval NSData的*为所有的数组的对象,像这样。

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

,它加载的一切是这样的: 的NSData * p1archv = [aDecoder decodeObjectForKey:@ “阶段1”];

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"]; 

的卡片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由一个NSArrayController管理)想要将数据加载到它在运行时崩溃的表视图中,或者它显示像eg “1:918”逐步完成。我肯定,在加载过程中,我还没有发布阵列或boxName或任何东西,所以我不能解释这个问题。我会很高兴,如果你能帮助我,Elefantosque

回答

6

我怀疑你的问题是decodeObjectForKey总是会返回一个autoreleased对象的事实。因此:

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中的字符串。我的猜测是,如果你改变属性行和赋值行,你的bug将会消失(尽管你可能有其他的)。

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

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

规则:除非您使用[页头]假设对象会被自动释放。

相关问题