2009-07-25 6 views
2

Je n'arrive pas à configurer un objet de modèle pour enregistrer l'état visuel des CALayers générés par l'utilisateur dans une application graphique simple pour l'iPhone. Je tente d'enregistrer la couleur d'arrière-plan et l'image de tous les calques courants à l'écran en transmettant ces propriétés aux objets de modèle qui implémentent le protocole NSCoding, puis à un NSMutableArray que possède le délégué de l'application. Ensuite, j'archive le tableau avec NSKeyedArchiver et le stocke dans le NSUserDefaults.L'archivage et le désarchivage entraînent un accès incorrect

La propriété backgroundColor de chaque CALayer est convertie en UIColor pour être codée par l'objet modèle pour le stockage. Je pense que je désarchive incorrectement le tableau ou ne restaure pas correctement l'état du tableau non archivé. Lorsque j'essaie d'accéder à l'objet UIColor stocké dans l'objet de modèle, j'obtiens un EXC_BAD_ACCESS. Je pensais que c'était peut-être un bug avec l'encodage des objets UIColor alors j'ai essayé de retirer les valeurs de CGColorRef avec la fonction CGColorGetComponents et de les stocker dans un tableau pour encoder et archiver, mais j'ai eu le même résultat de mauvais accès après désarchivage , donc je pense que je le fais juste mal.

Ceci est mon objet modèle:

@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 

Et voici ma mise en œuvre d'archivage:

@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 

Et voici où je ramènerai état:

@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 

Toute aide à ce est grandement apprécié. Je suis à peu près un noob. J'ai codé, archivé et désarchivé un NSArray de NSNumbers converti à partir des flottants de la couleur à peu près de la même manière et obtenant un mauvais accès.

Répondre

3

Vous voulez certainement conserver la couleur dans initWithCoder:

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

ou, avec la syntaxe de points que la couleur a été déclaré retenir propriété:

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

Voir ma réponse mise à jour pour la déclaration de propriété. – 0xced

0

Vous êtes en train de lâcher layerColor: Vous ne le possédez pas (layerDataObject), mais vous le débloquez.

+0

Ok. J'ai enlevé ça. Mais ça ne va pas aussi loin. Dès que j'essaie d'accéder à layerDataObject.color, il se bloque. Est-ce la bonne façon de restaurer un tableau à partir de données archivées? –

+0

C'est correct. À quoi ressemble le '- [AILayerData initWithCoder:]'? (Vous aurez besoin de modifier votre question, bien sûr.) –

+0

La mise en œuvre est au sommet. Mais je n'appelle pas cette méthode directement. Ai-je besoin de faire ça? En regardant les échantillons et la documentation, il semble que les objets non hiérarchisés réinitialisent tous les objets et appellent initWithCoder: en arrière-plan. Est-ce exact? –

Questions connexes