Архивирование и разархивирование приводит к плохому доступу
-
19-09-2019 - |
Вопрос
У меня возникли проблемы с настройкой объекта model для сохранения визуального состояния пользовательских CALayers в простом графическом приложении для iphone.
Я пытаюсь сохранить цвет фона и рамку всех текущих слоев на экране, передавая эти свойства объектам модели, которые реализуют протокол NSCoding, а затем в NSMutableArray, которым владеет делегат приложения.Затем я архивирую массив с помощью NSKeyedArchiver и сохраняю его в NSUserDefaults .
Свойство backgroundColor каждого CALayer преобразуется в UIColor, который будет закодирован объектом model для хранения.Я думаю, что я неправильно разархивирую массив или неправильно восстанавливаю состояние из неархивированного массива.Когда я пытаюсь получить доступ к объекту UIColor, который был сохранен в объекте model, я получаю EXC_BAD_ACCESS .
Я подумал, что, возможно, это ошибка с кодированием объектов UIColor, поэтому попытался извлечь значения из CGColorRef с помощью функции CGColorGetComponents и сохранить их в массиве для кодирования и архивирования, но у меня был тот же результат плохого доступа после разархивирования, поэтому я думаю, что я просто делаю это неправильно.
Это мой модельный объект:
@interface AILayerData : NSObject <NSCoding> {
UIColor* color;
CGRect frame;
}
@property (retain) UIColor* color;
@property (assign) CGRect frame;
@end
@implementation AILayerData
@synthesize color;
@synthesize frame;
- (void)encodeWithCoder:(NSCoder *)coder;
{
[coder encodeObject:color forKey:@"color"];
[coder encodeCGRect:frame forKey:@"frame"];
}
- (id)initWithCoder:(NSCoder *)coder;
{
self = [[AILayerData alloc] init];
if (self != nil)
{
color = [coder decodeObjectForKey:@"color"];
frame = [coder decodeCGRectForKey:@"frame"];
}
return self;
}
@end
И это моя реализация архивирования:
@implementation AppDelegate
- (void)applicationWillTerminate:(UIApplication *)application {
NSArray *layersArray = viewController.view.layer.sublayers;
dataArray = [NSMutableArray array];
for(AILayer *layer in layersArray)
{
AILayerData *layerData = [[AILayerData alloc] init];
layerData.frame = layer.frame;
UIColor *layerColor = [UIColor colorWithCGColor:layer.backgroundColor];
layerData.color = layerColor;
[dataArray addObject:layerData];
[layerData release];
}
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:layerDataArray] forKey:@"savedArray"];
}
@end
И вот здесь я восстанавливаю состояние:
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
spaceView = [[AISpaceView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.view = spaceView;
[spaceView release];
spaceView.delegate = self;
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"savedArray"];
if (dataRepresentingSavedArray != nil) {
[self restoreStateWithData:dataRepresentingSavedArray];
}
}
- (void)restoreStateWithData:(NSData *)data
{
NSArray *savedLayers = [NSKeyedUnarchiver unarchiveObjectWithData:data];
if (savedLayers != nil) {
NSArray *restoredLayers = [[NSArray alloc] initWithArray:savedLayers];
for(AILayerData *layerDataObject in restoredLayers) {
UIColor *layerColor = layerDataObject.color;
AILayer *newLayer = [[AILayer alloc] init];
newLayer.backgroundColor = layerColor.CGColor;
newLayer.frame = layerDataObject.frame;
newLayer.isSelected = NO;
[self.view.layer addSublayer:newLayer];
[newLayer release];
}
[restoredLayers release];
[spaceView.layer layoutSublayers];
}
}
@end
Любая помощь в этом очень ценится.Я в значительной степени нуб.Я кодировал, архивировал и разархивировал NSNumbers NSArray, преобразованный из значений с плавающей точкой цвета, практически таким же образом и получал плохой доступ.
Решение
Вы, конечно, хотите сохранить цвет в initWithCoder:
color = [[coder decodeObjectForKey:@"color"] retain];
или, с синтаксисом точки, поскольку цвет был объявлен как сохранить свойство:
self.color = [coder decodeObjectForKey:@"color"];
Другие советы
Вы чрезмерно высвобождаете layerColor
:Он тебе не принадлежит (layerDataObject
делает), но вы освобождаете его.
Похоже, что NSCoder для iPhone не отвечает на -encodeWithCGRect: