това е един от многото EXC_BADACCES въпроси, но проучвах дълго време и мисля, че този въпрос все още не е получил отговор. Моето приложение запазва данни с в предпочитанията. Всичко мина добре, ако изтрия предпочитанията и стартирам приложението, така че изобщо да не се зарежда. Но ако зареждането се случи, има проблем. Трябва да запазя един основен масив, който съдържа самозаписани обекти, наречен Box. Една кутия има NSString* boxName и шест NSMutableArray*, които съдържат друг самостоятелно написан обект, наречен Flashcard, който съдържа два NSString*: въпрос и отговор. Ако AppDelegate получи съобщението applicationWillTerminate, той кодира основния масив (наречен boxArray) с помощта на NSKeyedArchiver и го записва в предпочитанията. В метода init на AppControll този архив се зарежда от предпочитанията:
- (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 на Box, той създава 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"];
Флашкартите 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 и той показа точно същия ред. По време на моето проучване направих спирачни точки за всеки отделен метод и открих, че в метода init with coder на Box всичко е наред и boxName е това, което трябва да бъде (напр. "foo"), но ако tableview (Managed от NSArrayController) иска да зареди данните в табличния изглед, в който се срива, докато работи, или показва неща като напр. "1:918" при преминаване през отделните стъпки. Сигурен съм, че не съм освободил масива, или boxName, или каквото и да било преди в процеса на зареждане, така че не мога да обясня този проблем. Ще се радвам, ако можете да ми помогнете, Elefantosque