2013-04-08 8 views
1

plist에 저장하려는 사용자 지정 NSObject 클래스가 있습니다. 한 부분을 제외하고 올바르게 저장하고로드했습니다. 그뿐만 아니라 저장하려는 클래스에 사용자 지정 MKOverlay 클래스 개체가 있습니다. 부스러기가 NSCoding을 따르기 때문에 오류가 발생하지 않지만 앱을 저장하고 다시 연 후 오버레이가지도에 표시되지 않습니다. 빵 부스러기 객체는 0이 아니지만 여전히 표시되지 않습니다.NSCoder를 사용하여 사용자 지정 MKOverlay 저장

Trails.h

@interface Trails : NSObject <NSCoding> 
{ 
    @public 
    int topSpeed; 
    float avgSpeed; 
} 
@property (nonatomic, strong) NSString *miles; 
@property (nonatomic, strong) NSDate *date; 
@property (nonatomic, strong) NSString *time; 
@property (nonatomic, strong) CrumbPath *crumbs; 
- (NSString *)displayDate; 
- (NSString *)displayStartTime; 
- (void)addTopSpeed: (int)top withAvgSpeed:(float)avg; 
@end 

Trails.m

- (void)encodeWithCoder:(NSCoder *)coder { 
    [coder encodeObject:miles forKey:@"miles"]; 
    [coder encodeObject:date forKey:@"date"]; 
    [coder encodeObject:time forKey:@"time"]; 
    [coder encodeObject:crumbs forKey:@"crumbs"]; 
    [coder encodeFloat:avgSpeed forKey:@"avgSpeed"]; 
    [coder encodeInt:topSpeed forKey:@"topSpeed"]; 

} 


- (id)initWithCoder:(NSCoder *)coder { 
    self = [super init]; 
    if(self != nil) 
    { 
     miles = [coder decodeObjectForKey:@"miles"]; 
     date = [coder decodeObjectForKey:@"date"]; 
     time = [coder decodeObjectForKey:@"time"]; 
     crumbs = [coder decodeObjectForKey:@"crumbs"]; 
     avgSpeed = [coder decodeFloatForKey:@"avgSpeed"]; 
     topSpeed = [coder decodeIntForKey:@"topSpeed"]; 
    } 
    return self; 
} 

Crumbs.h

@interface CrumbPath : NSObject <MKOverlay, NSCoding> 

Crumbs.m

#import "CrumbPath.h" 

#define INITIAL_POINT_SPACE 1000 
#define MINIMUM_DELTA_METERS 10.0 

@implementation CrumbPath 

@synthesize points, pointCount; 

- (id)initWithCenterCoordinate:(CLLocationCoordinate2D)coord 
{ 
    self = [super init]; 
    if (self) 
    { 
     // initialize point storage and place this first coordinate in it 
     pointSpace = INITIAL_POINT_SPACE; 
     points = malloc(sizeof(MKMapPoint) * pointSpace); 
     points[0] = MKMapPointForCoordinate(coord); 
     pointCount = 1; 

     // bite off up to 1/4 of the world to draw into. 
     MKMapPoint origin = points[0]; 
     origin.x -= MKMapSizeWorld.width/8.0; 
     origin.y -= MKMapSizeWorld.height/8.0; 
     MKMapSize size = MKMapSizeWorld; 
     size.width /= 4.0; 
     size.height /= 4.0; 
     boundingMapRect = (MKMapRect) { origin, size }; 
     MKMapRect worldRect = MKMapRectMake(0, 0, MKMapSizeWorld.width, MKMapSizeWorld.height); 
     boundingMapRect = MKMapRectIntersection(boundingMapRect, worldRect); 

     // initialize read-write lock for drawing and updates 
     pthread_rwlock_init(&rwLock, NULL); 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    free(points); 
    pthread_rwlock_destroy(&rwLock); 
} 

- (CLLocationCoordinate2D)coordinate 
{ 
    return MKCoordinateForMapPoint(points[0]); 
} 

- (MKMapRect)boundingMapRect 
{ 
    return boundingMapRect; 
} 

- (void)lockForReading 
{ 
    pthread_rwlock_rdlock(&rwLock); 
} 

- (void)unlockForReading 
{ 
    pthread_rwlock_unlock(&rwLock); 
} 

- (MKMapRect)addCoordinate:(CLLocationCoordinate2D)coord 
{ 
    // Acquire the write lock because we are going to be changing the list of points 
    pthread_rwlock_wrlock(&rwLock); 

    // Convert a CLLocationCoordinate2D to an MKMapPoint 
    MKMapPoint newPoint = MKMapPointForCoordinate(coord); 
    MKMapPoint prevPoint = points[pointCount - 1]; 

    // Get the distance between this new point and the previous point. 
    CLLocationDistance metersApart = MKMetersBetweenMapPoints(newPoint, prevPoint); 
    MKMapRect updateRect = MKMapRectNull; 

    if (metersApart > MINIMUM_DELTA_METERS) 
    { 
     // Grow the points array if necessary 
     if (pointSpace == pointCount) 
     { 
      pointSpace *= 2; 
      points = realloc(points, sizeof(MKMapPoint) * pointSpace); 
     }  

     // Add the new point to the points array 
     points[pointCount] = newPoint; 
     pointCount++; 

     // Compute MKMapRect bounding prevPoint and newPoint 
     double minX = MIN(newPoint.x, prevPoint.x); 
     double minY = MIN(newPoint.y, prevPoint.y); 
     double maxX = MAX(newPoint.x, prevPoint.x); 
     double maxY = MAX(newPoint.y, prevPoint.y); 

     updateRect = MKMapRectMake(minX, minY, maxX - minX, maxY - minY); 
    } 

    pthread_rwlock_unlock(&rwLock); 

    return updateRect; 
} 

//Conform to NSCoding 
- (void)encodeWithCoder:(NSCoder *)coder { 
    //I think I need to do something here? 
} 


- (id)initWithCoder:(NSCoder *)coder { 
    self = [super init]; 
    if(self != nil) 
    { 
     //I think I need to do something here? 
    } 
    return self; 
} 

@end 
+0

을 당신이 어떤 데이터가없는/CrumbPath 클래스의 속성? 저장되는 것을 보지 마라. 나는 MKOverlay 프로토콜을 따르는 객체가'coordinate'와'boundingMapRect' 속성을 필요로한다고 생각했습니다. –

+0

예, 각 파일의 전체 코드를 포함하지 않았으므로 전체 CrumbPath.m을 표시하도록 코드를 업데이트했습니다. – Glen

답변

2

CrumbPath 클래스의 encodeWithCoderinitWithCoder 구현이 비어 있습니다. Trails 개체와 마찬가지로 모든 속성/ivars를 저장해야합니다. 모든 객체는 NSCoding과 관련된 자신의 속성/ivars를 저장합니다.

그냥 추가하면 CLLocationCoordinate2D 및 CGRect를 디스크에 직접 쓸 수 없습니다. 그들을 분해하고 다시 구성해야합니다.

[aCoder encodeFloat:rect.origin.x forKey:@"x"]; 
[aCoder encodeFloat:rect.origin.y forKey:@"y"]; 
[aCoder encodeFloat:rect.size.width forKey:@"width"]; 
[aCoder encodeFloat:rect.size.height forKey:@"height"]; 

및 다음/init'ing를 디코딩 할 때, 당신이 그것을 재구성해야한다 : 예를 들어, 다음과 같이 CGRect, 당신은 인코딩해야

CGFloat x = [aDecoder decodeFloatForKey:@"x"]; 
CGFloat y = [aDecoder decodeFloatForKey:@"y"]; 
CGFloat width = [aDecoder decodeFloatForKey:@"width"]; 
CGFloat height = [aDecoder decodeFloatForKey:@"height"]; 

self.rect = CGRectMake(x,y,width,height); 
+0

명확한 답변이 지금은 완벽하게 작동 해 주셔서 감사합니다. :) – Glen

+0

내가 도와 줄 수있어서 기쁘다. 대답을 수락하는 것을 잊지 마시기 바랍니다. –