Core data 如何将NSMutable阵列中的数据存储在核心数据中?

Core data 如何将NSMutable阵列中的数据存储在核心数据中?,core-data,nsmutablearray,store,polyline,persist,Core Data,Nsmutablearray,Store,Polyline,Persist,我正在制作的应用程序根据CLLocationManager中的用户坐标绘制一条多段线(这些都保存在NSMutableArray) 应用程序关闭时,当前多段线将消失。如何在CoreData中存储应用程序启动时要检索的点阵列?用户自启动应用程序以来采取的所有过去的“路线”都应该恢复并覆盖在地图上(这可能相当多,因此从我收集的数据来看,CoreData似乎是最好的选择) 这是我用来从加载的坐标创建MKPolyline的代码 -(IBAction)didClickLoadCoordinates:(id)

我正在制作的应用程序根据
CLLocationManager
中的用户坐标绘制一条
多段线(这些都保存在
NSMutableArray

应用程序关闭时,当前多段线将消失。如何在CoreData中存储应用程序启动时要检索的点阵列?用户自启动应用程序以来采取的所有过去的“路线”都应该恢复并覆盖在地图上(这可能相当多,因此从我收集的数据来看,CoreData似乎是最好的选择)

这是我用来从加载的坐标创建MKPolyline的代码

-(IBAction)didClickLoadCoordinates:(id)sender {
// get a reference to the appDelegate so you can access the global managedObjectContext
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Route"];
NSError *error;
id results = [appDelegate.managedObjectContext executeFetchRequest:request error:&error];

if ([results count]) {
    polyLine = (Route *)(results[0]);
    NSArray *coordinates = polyLine.coordinates;
    int ct = 0;
    for (CLLocation *loc in coordinates) {
        NSLog(@"location %d: %@", ct++, loc);


    }


    // this copies the array to your mutableArray
    _locationsArray = [coordinates mutableCopy];

}

NSInteger numberOfSteps = _locationsArray.count;

//convert to coordinates array to construct the polyline

CLLocationCoordinate2D clCoordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++) {
    CLLocation *location = [_locationsArray objectAtIndex:index];
    CLLocationCoordinate2D coordinate2 = location.coordinate;
    clCoordinates[index] = coordinate2;
}

MKPolyline *routeLine = [MKPolyline polylineWithCoordinates:clCoordinates count:numberOfSteps];
[_mapView addOverlay:routeLine];
-(iAction)didClickLoadCoordinates:(id)发送方{
//获取对appDelegate的引用,以便可以访问全局managedObjectContext
AppDelegate*AppDelegate=[UIApplication sharedApplication]。委托;
NSFetchRequest*请求=[[NSFetchRequest alloc]initWithEntityName:@“路由”];
n错误*错误;
id结果=[appDelegate.managedObjectContext executeFetchRequest:请求错误:&错误];
如果([结果计数]){
多段线=(路线*)(结果[0]);
NSArray*坐标=多段线坐标;
int-ct=0;
用于(坐标中的CLLocation*loc){
NSLog(@“位置%d:%@”,ct++,loc);
}
//这会将数组复制到mutableArray
_位置数组=[坐标可变复制];
}
NSInteger numberOfSteps=\u locationsArray.count;
//转换为坐标数组以构造多段线
CLLocationCoordination2D CLCoordinations[步数];
对于(NSInteger index=0;index
我创建了一个简单的类,该类在应用程序关闭时用数组保存一条多段线,并在应用程序返回时查询所有多段线的核心数据。我假设您知道如何设置核心数据和托管对象上下文。此模式允许您直接设置NSArray对象并将其放入核心数据对象。它背后的基本原理是这是:

首先,创建带有可转换属性(数组)和数据属性的模型

接下来,在多段线对象上创建一个类别

-(IBAction)didClickSaveCoordinates:(id)sender {
    /*
     NSInteger numberOfSteps = _locationsArray.count;
     // you don't need to convert it to a coordinates array.
     CLLocationCoordinate2D coordinates[numberOfSteps];
     for (NSInteger index = 0; index < numberOfSteps; index++) {
     CLLocation *location = [_locationsArray objectAtIndex:index];
     CLLocationCoordinate2D coordinate2 = location.coordinate;
     coordinates[index] = coordinate2;
     }
     */

    // get a reference to the appDelegate so you can access the global managedObjectContext
    AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;

    // creates a new polyline object when app goes into the background, and stores it into core data.
    if (!polyLine) {
        NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:@"Polyline" inManagedObjectContext:appDelegate.managedObjectContext];
        polyLine = (Polyline *)object;
    }

    [polyLine setCoordinates:_locationsArray];
    NSError *error;
    if ([appDelegate.managedObjectContext save:&error]) {
        NSLog(@"Saved");
    }
    else {
        NSLog(@"Error: %@", error);
    }
}

现在,您的文件浏览器中应该有这些项目

多段线+TransformableAttributes.h

#import "Polyline.h"

@interface Polyline (TransformableAttributes)

#pragma mark transformables

-(NSArray *)coordinates;
-(void)setCoordinates:(id)coordinates;

@end
多段线+TransformableAttributes.m

@implementation Polyline (TransformableAttributes)

#pragma mark Transformables
-(NSArray *)coordinates {
    if (!self.coordinates_data)
        return nil;

    return [NSKeyedUnarchiver unarchiveObjectWithData:self.coordinates_data];
}

-(void)setCoordinates:(id)coordinates {
    NSData *coordinates_data = [NSKeyedArchiver archivedDataWithRootObject:coordinates];
    [self setValue:coordinates_data forKey:@"coordinates_data"];
}

@end
Appdelegate.m

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Polyline"];
    NSError *error;
    id results = [self.managedObjectContext executeFetchRequest:request error:&error];
    Polyline *polyline = (Polyline *)(results[0]);
    NSArray *coordinates = polyline.coordinates;

}

- (void)applicationWillResignActive:(UIApplication *)application
{
    NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:@"Polyline" inManagedObjectContext:self.managedObjectContext];
    Polyline *polyline = (Polyline *)object;
    [polyline setCoordinates:@[@"a", @"b", @"c"]];
    NSError *error;
    if ([self.managedObjectContext save:&error]) {
        NSLog(@"Saved");
    }
    else {
        NSLog(@"Error: %@", error);
    }
}
请让我知道它是否对你有效。如果需要,我会更新我的答案,以便它能有用。我不记得我最初在哪里发现这个模式,但它确实很有帮助,而且投票率很高

编辑1:添加了gps视图

这是我添加的一个新控制器:

GPSViewController.h:

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import "Polyline+TransformableAttributes.h"

@interface GPSViewController : UIViewController <CLLocationManagerDelegate>
{
    NSMutableArray *_locationsArray;
    Polyline *polyLine;
    CLLocationManager *locationManager;
}

-(IBAction)didClickStartGPS:(id)sender;
-(IBAction)didClickSaveCoordinates:(id)sender;
-(IBAction)didClickLoadCoordinates:(id)sender;
单击GPS按钮时,它会显示在此处。locationManager是该类的实例变量

-(IBAction)didClickStartGPS:(id)sender {
    locationManager = [[CLLocationManager alloc] init];
    [locationManager setDelegate:self];
    [locationManager startUpdatingLocation];
}
这会将坐标保存到多段线中并将其保存。注意:使用此代码,我不会执行任何特定的搜索描述符,因此如果您多次单击“保存”,您将在核心数据中获得一组多段线,并且每次可能只加载第一条多段线。如果添加,您可以通过这些多段线搜索特定的id或日期将其添加到多段线对象

-(IBAction)didClickSaveCoordinates:(id)sender {
    /*
     NSInteger numberOfSteps = _locationsArray.count;
     // you don't need to convert it to a coordinates array.
     CLLocationCoordinate2D coordinates[numberOfSteps];
     for (NSInteger index = 0; index < numberOfSteps; index++) {
     CLLocation *location = [_locationsArray objectAtIndex:index];
     CLLocationCoordinate2D coordinate2 = location.coordinate;
     coordinates[index] = coordinate2;
     }
     */

    // get a reference to the appDelegate so you can access the global managedObjectContext
    AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;

    // creates a new polyline object when app goes into the background, and stores it into core data.
    if (!polyLine) {
        NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:@"Polyline" inManagedObjectContext:appDelegate.managedObjectContext];
        polyLine = (Polyline *)object;
    }

    [polyLine setCoordinates:_locationsArray];
    NSError *error;
    if ([appDelegate.managedObjectContext save:&error]) {
        NSLog(@"Saved");
    }
    else {
        NSLog(@"Error: %@", error);
    }
}
此代码在my github上更新:

github.com/bobbyren/StackOverflowTest.git

编辑:要为每条多段线添加新的多段线,请执行以下操作:

NSArray *polylines = [fetchedResultsController allObjects];
for (Polyline *polyline in polylines) {
    MKPolyline *mkPolyline = [MKPolyline polylineWithCoordinates:polyline.coordinates count:ct]; // assuming you have written out how to return polyline.coordinates as a CLLocationCoordinate2D[]
    [mapView addOverlay:line];
}

[mapView reloadData];

我使用可转换属性:。我实际上使用不可变属性,因为我不会经常保存到磁盘。如果您确切知道何时保存到磁盘(即在应用程序关闭或注销时),您基本上可以将阵列转换为NSData对象,并将其存储到核心数据对象中。如果您想了解我使用的模式的更多信息(包括对象上的类别)我可以发布它。好的,谢谢。我将保存数组(点数)在应用程序关闭之前或关闭时。您能给我一些关于将阵列转换为NSData对象并保存在Core Data中的更多信息吗?@mitrenegadeok,这样看起来您正在拉出Core Data中的第一条多段线并显示该多段线。当用户移动/创建新坐标时,您是否将其添加到同一阵列中?是否有一个单独的a将加载的坐标放入其中,然后向其中添加新坐标的数组?您可以每次将一组坐标保存到新的多段线中,并将其存储到核心数据中。然后,您可以存储多段线数组=(NSArray*),而不仅仅是使用多段线=(Route*)(结果[0])或者,如果您不需要存储旧的多段线,只需绘制它们,只需将我给您的代码放入一个对结果进行迭代的数组中即可。对于((Route*)results中的Route){…对结果执行所有其他操作(0)}所有CLLocation都存储在locationsArray中(加载的坐标也复制到此数组中)。由此,我得到CLLOCATIONCoordinates 2D。因此,是的,只有一个数组加载了新坐标并添加了新坐标。我想这就是加载的多段线与新更新的cllocation多段线连接的原因…我只需要将这些线分开,但仍然需要所有旧的多段线。想想看我的应用程序正在创建一个巨大的多段线网络,无论用户身在何处,但当应用程序关闭时,显然会出现问题。我是一个初学者,所以我目前正在阅读核心数据和管理对象等。标记为已回答的图像和详细信息-将很快阅读并实现。非常感谢!好的,那么我认为对于您的情况,请尝试sim卡这里的pler解决方案:。基本上,在保存核心数据时将阵列转换为nsdata,在加载阵列并需要访问阵列时将其取消归档。我认为阵列不能直接存储在核心数据中?在核心数据对象模型中,可以具有nsdata属性。这本质上是
NSArray *polylines = [fetchedResultsController allObjects];
for (Polyline *polyline in polylines) {
    MKPolyline *mkPolyline = [MKPolyline polylineWithCoordinates:polyline.coordinates count:ct]; // assuming you have written out how to return polyline.coordinates as a CLLocationCoordinate2D[]
    [mapView addOverlay:line];
}

[mapView reloadData];