Архивирование и разархивирование результатов в Bad Access - PullRequest
2 голосов
/ 25 июля 2009

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

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

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

3 голосов
/ 26 июля 2009

Вы, безусловно, хотите сохранить цвет в initWithCoder:

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

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

self.color = [coder decodeObjectForKey:@"color"];
0 голосов
/ 27 июля 2009

Похоже, что NSCoder для iPhone не отвечает на -encodeWithCGRect:

Источник: http://17.254.2.129/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSCoder_Class/Reference/NSCoder.html

0 голосов
/ 25 июля 2009

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

...