2009-07-25 2 views
2

У меня возникли проблемы с настройкой объекта модели для сохранения визуального состояния созданных пользователем CALayers в простом графическом приложении для iphone.Архивирование и Unarchiving приводит к неправильному доступу

Я пытаюсь сохранить цвет фона и кадр всех текущих слоев на экране, передав эти свойства для моделирования объектов, которые реализуют протокол NSCoding, а затем в NSMutableArray, которому принадлежит делегат приложения. Затем я архивирую массив с NSKeyedArchiver и сохраняю его в NSUserDefaults.

Свойство backgroundColor каждого CALayer преобразуется в UIColor, который должен быть закодирован объектом модели для хранения. Я думаю, что я unarchiving массив неправильно или не восстанавливает состояние из unarchived массива правильно. Когда я пытаюсь получить доступ к объекту UIColor, хранящемуся в объекте модели, я получаю 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 

Любая помощь с этим очень ценится. Я почти нуб. Я кодировал, архивировал и сворачивал NSArray из NSNumbers, преобразованный из поплавков цвета, практически так же, как и плохой доступ.

ответ

3

Вы, конечно, хотите, чтобы сохранить цвет в initWithCoder:

color = [[coder decodeObjectForKey:@"color"] retain]; 

или, с синтаксисом точка, как цвет был объявлен как сохранить свойство:

self.color = [coder decodeObjectForKey:@"color"]; 
+0

См. Мой обновленный ответ для объявления свойства. – 0xced

0

Вы перевыпускаете layerColor: Вы не являетесь владельцем (layerDataObject), но вы его выпускаете.

+0

Хорошо. Я понял это. Но это далеко не так. Как только я попытаюсь получить доступ к layerDataObject.color, он сработает. Это правильный способ восстановления массива из архивных данных? –

+0

Это правильно. Что выглядит '- [AILayerData initWithCoder:]'? (Вам, конечно, нужно будет отредактировать свой вопрос.) –

+0

Реализация находится наверху. Но я не называю этот метод напрямую. Нужно ли мне это делать? От взгляда на образцы и документацию это выглядит как unarching объекты повторно инициализировать все объекты и вызывает initWithCoder: в фоновом режиме. Это верно? –

Смежные вопросы