归档和取消归档会导致访问不良

时间:2009-07-25 18:32:45

标签: cocoa cocoa-touch uikit nsuserdefaults nskeyedarchiver

我在设置模型对象时遇到问题,无法将用户生成的CALayers的可视状态保存在iphone的简单图形应用程序中。

我试图通过将这些属性传递给实现NSCoding协议的模型对象,然后传递到app delegate拥有的NSMutableArray,来保存屏幕上所有当前图层的背景颜色和框架。然后我用NSKeyedArchiver归档数组并将其存储在NSUserDefaults中。

每个CALayer的backgroundColor属性都转换为UIColor,由模型对象进行编码以进行存储。我认为我正确地解析了数组或者没有正确地从unarchived数据中恢复状态。当我尝试访问存储在模型对象中的UIColor对象时,我得到一个EXC_BAD_ACCESS。

我认为这可能是编码UIColor对象的错误所以尝试使用CGColorGetComponents函数从CGColorRef中提取值并将它们存储在数组中进行编码和存档,但是在取消存档后我得到了相同的错误访问结果,所以我想我做错了。

这是我的模型对象:

@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的NSNrray,它们从颜色的浮动中转换成几乎相同的方式并且访问不良。

3 个答案:

答案 0 :(得分:3)

您当然希望在initWithCoder中保留颜色:

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

或者,使用点语法将颜色声明为保留属性:

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

答案 1 :(得分:0)

你过度释放layerColor:你不拥有它(layerDataObject确实如此),但你正在释放它。

答案 2 :(得分:0)