54763

Archiving and Unarchiving results in Bad Access

I'm having trouble setting up a model object to save the visual state of user generated CALayers in a simple graphics application for the iphone.

I'm attempting to save the background color and frame of all the current layers on screen by passing those properties to model objects which implement the NSCoding protocol and then into an NSMutableArray which the app delegate owns. Then I archive the array with NSKeyedArchiver and store it in the NSUserDefaults.

Each CALayer's backgroundColor property is converted to a UIColor to be encoded by the model object for storage. I think that I'm unarchiving the array incorrectly or not restoring state from the unarchived array correctly. When I attempt to access the UIColor object that was store in the model object, I get an EXC_BAD_ACCESS.

I thought it was possibly a bug with encoding UIColor objects so tried pulling the values out of the CGColorRef with the CGColorGetComponents function and storing them in an array to encode and archive, but I had the same result of bad access after unarchiving, so I think I'm just doing it wrong.

This is my model object:

@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

And this is my archiving implementation:

@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

And here is where I restore state:

@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

Any help with this is greatly appreciated. I'm pretty much a noob. I was encoding, archiving and unarching an NSArray of NSNumbers converted from the color's floats in pretty much the same way and getting bad access.

Answer1:

You certainly want to retain the color in initWithCoder:

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

or, with the dot syntax as color was declared as a retain property:

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

Answer2:

You are over-releasing layerColor: You don't own it (layerDataObject does), but you are releasing it.

Answer3:

It looks like NSCoder for iPhone doesn't respond to -encodeWithCGRect:

Source: http://17.254.2.129/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSCoder_Class/Reference/NSCoder.html

Recommend

  • how to draw vertical line in UIScrollView
  • main loop 'builtin_function_or_method' object is not iterable
  • XMPP push notifications causing problems (delay + duplications) in messages
  • Configure Webpack to build a directory of LESS files into corresponding CSS files
  • Excel not inserting leading zero
  • iPhone - UIWebView multiple locks
  • What is wrong in my MVC implementation?
  • How to get to older Xcode beta version?
  • Safari PHP form submission -file upload hangs
  • Retrieving a contacts notes
  • How do I obtain a list of files that changed from svn over a date range?
  • Special chars in Amazon S3 keys?
  • Encode Byte array to JPEG image in Objective-C
  • android-support-v7-appcompat has same attrs as actionbarsherlock library
  • Serve file to user over http via php
  • MVC - @Html.CheckBoxFor
  • Unique Permutations - with exceptions
  • Ionic 2 storage is not cleaning up on uninstall - Only for signed APK
  • Is there any way to access browser form field suggestions from JavaScript?
  • Encrypt data by using a public key in c# and decrypt data by using a private key in php
  • RectangularRangeIndicator format like triangular using dojo
  • SSO with signing and signature validation doesn't work
  • Deserializing XML into class C#
  • Convert array of 8 bytes to signed long in C++
  • Calling of Constructors in a Java
  • bootstrap to use multiple ng-app
  • Comma separated Values
  • How to delete a row from a dynamic generate table using jquery?
  • How to set the response of a form post action to a iframe source?
  • Understanding cpu registers
  • python draw pie shapes with colour filled
  • Are Kotlin's Float, Int etc optimised to built-in types in the JVM? [duplicate]
  • Recursive/Hierarchical Query Using Postgres
  • Running Map reduces the dimensions of the matrices
  • costura.fody for a dll that references another dll
  • Reading document lines to the user (python)
  • Binding checkboxes to object values in AngularJs
  • Net Present Value in Excel for Grouped Recurring CF
  • jQuery Masonry / Isotope and fluid images: Momentary overlap on window resize
  • How to load view controller without button in storyboard?