2013-03-01 91 views
2

我正在编写一个iOS应用程序来记录您的旅行路径,然后将其存储起来以便稍后可以检索它。绘制路径的大部分代码都基于示例代码Breadcrumb如何将MKOverlay对象存储到文件以供稍后检索

现在我正在添加功能以保存绘制的叠加层。什么是最好的方式来做到这一点?我可以使用CoreData,但我不希望对绘制的叠加层做很多工作,而不是稍后再检索它。我目前已经尝试了一个简单的NSArray。我将CrumbPath对象转换为NSData并将其存储在数组中。稍后我会检索它并将其转换回CrumbPath。但是,我似乎做错了什么。

@interface CrumbPath : NSObject <MKOverlay> 
{ 
    MKMapPoint *points; 
    NSUInteger pointCount; 
    NSUInteger pointSpace; 

    MKMapRect boundingMapRect; 

    pthread_rwlock_t rwLock; 
} 

- (id)initWithCenterCoordinate:(CLLocationCoordinate2D)coord; 
- (MKMapRect)addCoordinate:(CLLocationCoordinate2D)coord; 

@property (readonly) MKMapPoint *points; 
@property (readonly) NSUInteger pointCount; 

@end 

我节省CrumbPath对象 “面包屑” 是这样的:

NSData *pointData = [NSData dataWithBytes:crumbs.points length:crumbs.pointCount * sizeof(MKMapPoint)]; 
[patternArray addObject:pointData]; 
[timeArray addObject:date]; 

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
// Create the full file path by appending the desired file name 
NSString *patternFile = [documentsDirectory stringByAppendingPathComponent:@"patterns.dat"]; 
NSString *timeFile = [documentsDirectory stringByAppendingPathComponent:@"times.dat"]; 

//Save the array 
[patternArray writeToFile:patternFile atomically:YES]; 
[timeArray writeToFile:timeFile atomically:YES]; 

后来这样获取在表中显示:

NSData *pointData = [appDelegate.patternArray objectAtIndex:indexPath.row]; 
MKMapPoint *points = malloc(pointData.length); 
(void)memcpy([pointData bytes], points, sizeof(pointData)); 

并再次构建路径:

crumbs = [[CrumbPath alloc] initWithCenterCoordinate:MKCoordinateForMapPoint(points[0])]; 
for (int i = 1; i <= pointCount; i++) { 
    [crumbs addCoordinate:MKCoordinateForMapPoint(points[i])]; 
}  
[map addOverlay:crumbs]; 

但是,我得到一个错误:'NSInvalidArgumentException', reason: '-[NSConcreteData isEqualToString:]: unrecognized selector sent to instance

+0

与您的例外无关,您向我们显示您对'malloc'的调用,但不显示相应的'免费'调用。我假设你有这个地方,但确保你自己清理。或者你可以避免调用'malloc'和'memcpy'(就像我下面的代码示例),你不必担心它。 – Rob 2013-03-01 04:09:35

回答

2

就个人而言,我倾向于做如下:

  1. 首先,我会倾向于节省CLLocationCoordinate2D C数组坐标,我传递给MKPolygon实例方法polygonWithCoordinates(而不是一个MKMapPoint C数组)。如果您愿意使用MKMapPoints,则可以修改此代码,但我更喜欢一种格式,我可以从外部检查并理解(即CLLocationCoordinate2D的经度和纬度值)。所以,让我们假设你让你MKPolygon,象这样一行代码:

    MKPolygon* poly = [MKPolygon polygonWithCoordinates:coordinates count:count]; 
    

    你可以因此节省坐标,像这样:

    [self writeCoordinates:coordinates count:count file:filename]; 
    

    writeCoordinates:count:filename:定义如下:

    0123:
    - (void)writeCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count file:(NSString *)filename 
    { 
        NSData *data = [NSData dataWithBytes:coordinates length:count * sizeof(CLLocationCoordinate2D)]; 
        [data writeToFile:filename atomically:NO]; 
    } 
    

    然后,您可以用使MKPolygon从文件

    其中polygonWithContentsOfFile定义为:

    - (MKPolygon *)polygonWithContentsOfFile:(NSString *)filename 
    { 
        NSData *data = [NSData dataWithContentsOfFile:filename]; 
        NSUInteger count = data.length/sizeof(CLLocationCoordinate2D); 
        CLLocationCoordinate2D *coordinates = (CLLocationCoordinate2D *)data.bytes; 
    
        return [MKPolygon polygonWithCoordinates:coordinates count:count]; 
    } 
    
  2. 或者,也可以读出并在一个的plist格式写的CLLocationCoordinate2D阵列(这使其在人类可读的格式),通过替换上述两种方式搭配:

    const NSString *kLatitudeKey = @"latitude"; 
    const NSString *kLongitudeKey = @"longitude"; 
    
    - (void)writeCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count file:(NSString *)filename 
    { 
        NSMutableArray *array = [NSMutableArray arrayWithCapacity:count]; 
    
        for (NSUInteger i = 0; i < count; i++) 
        { 
         CLLocationCoordinate2D coordinate = coordinates[i]; 
         [array addObject:@{kLatitudeKey:@(coordinate.latitude), kLongitudeKey:@(coordinate.longitude)}]; 
        } 
    
        [array writeToFile:filename atomically:NO]; 
    } 
    
    - (MKPolygon *)polygonWithContentsOfFile:(NSString *)filename 
    {   
        NSArray *array = [NSArray arrayWithContentsOfFile:filename]; 
        NSUInteger count = [array count]; 
        CLLocationCoordinate2D coordinates[count]; 
    
        for (NSUInteger i = 0; i < count; i++) 
        { 
         NSDictionary *dictionary = array[i]; 
         coordinates[i].latitude = [dictionary[kLatitudeKey] doubleValue]; 
         coordinates[i].longitude = [dictionary[kLongitudeKey] doubleValue]; 
        } 
    
        return [MKPolygon polygonWithCoordinates:coordinates count:count]; 
    } 
    

显然你需要添加错误校验码,以确保该writeToFiledataWithContentsOfFile(或arrayWithContentsOfFile)成功,但希望这给你的想法。

+0

谢谢Rob。我会尝试这两种方法。但是,你有什么想法,为什么我得到这个错误。 – Sap 2013-03-01 03:51:53

+0

@Sap我怀疑这个错误不是来自你问题中的代码,而是某个你调用'isEqualToString'的地方,但是所讨论的对象是一个'NSData',而不是'NSString'。我建议在代码中搜索“isEqualToString”的出现次数。底线,你真的必须确定产生该异常的精确的代码行。您可以单步执行代码或添加[异常断点](http://developer.apple.com/library/mac/#recipes/xcode_help-breakpoint_navigator/articles/adding_an_exception_breakpoint.html)来识别违规代码。 – Rob 2013-03-01 04:06:56

+0

我最初试图修改MKMapPoints的代码。我仍然无法保存文件。但是,我放弃了并按照您的建议存储了坐标。有用。谢谢! – Sap 2013-03-03 11:45:50

相关问题