【问题标题】:Archiving and Unarchiving results in Bad Access归档和取消归档导致访问不正确
【发布时间】:2009-07-25 18:32:45
【问题描述】:

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

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

每个 CALayer 的 backgroundColor 属性都转换为 UIColor 以由模型对象编码以进行存储。我认为我错误地取消了阵列或未正确地从未归档的阵列恢复状态。当我尝试访问存储在模型对象中的 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

非常感谢您对此的任何帮助。我几乎是个菜鸟。我正在以几乎相同的方式对从颜色的浮点数转换而来的 NSNumber 的 NSArray 进行编码、归档和解构,并且访问不正确。

【问题讨论】:

    标签: cocoa cocoa-touch uikit nsuserdefaults nskeyedarchiver


    【解决方案1】:

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

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

    或者,使用点语法作为颜色被声明为 retain 属性:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 好的。我已经把它拿出来了。但它并没有那么远。一旦我尝试访问 layerDataObject.color,它就会崩溃。这是从存档数据中恢复数组的正确方法吗?
      • 没错。 -[AILayerData initWithCoder:] 看起来像什么? (当然,您需要编辑您的问题。)
      • 实现在顶部。但我没有直接调用该方法。我需要这样做吗?从查看示例和文档来看,似乎解构对象重新初始化了所有对象并在后台调用 initWithCoder:。对吗?
      • 啊,现在我明白了。正确,解压器会为您发送initWithCoder: 到您的对象。但是,您需要将这些对象保留在那里。见:developer.apple.com/documentation/Cocoa/Conceptual/Archiving/…
      【解决方案3】:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-19
        • 1970-01-01
        • 2017-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多