2013-04-08 80 views
1

我有一个自定义的NSObject类我想保存到plist的Trails。我现在正确保存和加载,除了一部分。我有一个自定义的MKOverlay类对象面包屑,我想保存在该类中。由于面包屑符合NSCoding,所以不会抛出任何错误,但保存并重新打开应用程序后,覆盖图不会显示在地图上。面包屑对象不是零,但仍然不显示。使用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协议的对象需要一个“坐标”和一个“boundingMapRect”属性? – 2013-04-08 20:53:50

+0

是的,我没有包括每个文件的完整代码,我已经更新了代码以显示完整的CrumbPath.m – Glen 2013-04-08 21:05:00

回答

2

类的encodeWithCoderinitWithCoder的实现是空的。您需要保存所有属性/ ivars,与您为Trails对象所做的一样。所有对象都负责保存与NSCoding相关的属性/ ivars。

只需添加 - 您不能直接将CLLocationCoordinate2D和CGRect写入磁盘。你必须打破它们并重构它们。例如,使用的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时,你必须重新构建它:

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 2013-04-09 02:45:30

+0

很高兴我可以帮助 - 请不要忘记接受答案。 – 2013-04-09 02:54:33

相关问题