2009-07-25 3 views
2

아이폰 용 간단한 그래픽 응용 프로그램에서 사용자 생성 CALayers의 시각적 상태를 저장하기 위해 모델 객체를 설정하는 데 문제가 있습니다.보관 및 보관 취소가 불량 액세스로 발생합니다.

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 

이에 어떤 도움 대단히 감사합니다. 나는 꽤 멍청하다. NSNumbers의 NSArray를 인코딩하고 아카이브하고 unarching하여 거의 동일한 방식으로 색상의 부동 소수점을 변환하고 잘못된 액세스를 얻었습니다.

답변

3

당신은 확실히 initWithCoder 색상 유지하려면 : 색상은 속성을 유지하기로 선언되었을 때 도트 구문

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

이상을 :

그것은을 위해 NSCoder처럼 보이는
self.color = [coder decodeObjectForKey:@"color"]; 
+0

속성 선언에 대한 업데이트 된 답변을 확인하십시오. – 0xced

0

고객님은 아직 소유하고 있지 않습니다. (layerDataObject 않습니다), 귀하는 그것을 풀어 놓았습니다. layerColor : 당신은 그것을 소유하고 있지 않습니다.

+0

확인. 나는 그것을 꺼냈다. 그러나 그것은 그렇게까지 얻지 못합니다. layerDataObject.color에 액세스하려고하면 충돌이 발생합니다. 아카이브 된 데이터에서 어레이를 복원하는 올바른 방법입니까? –

+0

맞습니다. '- [AILayerData initWithCoder :]'는 어떻게 생겼습니까? (물론 질문을 편집해야합니다.) –

+0

구현이 맨 위에 있습니다. 그러나 나는 그 방법을 직접적으로 부르지 않을 것이다. 그 일을해야합니까? 샘플과 문서를 살펴보면, 모든 객체를 다시 초기화하고 백그라운드에서 initWithCoder :를 호출하는 것처럼 보이지 않는 객체처럼 보입니다. 그 맞습니까? –