你如何将 NSMutable Array 中的数据存储在 Core Data 中? [英] How do you store data from NSMutable Array in Core Data?

查看:24
本文介绍了你如何将 NSMutable Array 中的数据存储在 Core Data 中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作的应用程序根据来自 CLLocationManager 的用户坐标绘制一个 Polyline(这些都保存在 NSMutableArray 中)

The app i'm making draws a Polyline based on the users coordinates from CLLocationManager (these are all kept in an NSMutableArray)

当应用程序关闭时,当前折线消失.如何在应用程序启动时将要检索的点数组存储在 CoreData 中?应该恢复用户自启动应用程序以来采取的所有过去路线"并叠加在地图上(这可能很多,因此从我收集的信息来看,CoreData 似乎是最佳选择).

When the app closes, the current polyline disappears. How can I store the array of points in CoreData to be retrieved when the app starts up? All of the past 'routes' that the user has taken since initiating the app should be recovered and overlaid on the map (which may be quite a lot, so CoreData seems the best option from what i've gathered).

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

This is the code I use to create an MKPolyline from the loaded coordinates

-(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];

推荐答案

我创建了一个简单的类,它在应用程序关闭时用数组保存多段线,并在应用程序返回时查询所有多段线的核心数据.我假设您知道如何设置核心数据和托管对象上下文.这种模式允许您直接将 NSArray 对象设置和获取到核心数据对象中.它背后的基本原理在这里:https://coderwall.com/p/mx_wmq

I've created a simple class that saves a polyline with an array when the app closes, and queries core data for all polylines when the app returns. I assume you know how to set up core data and managed object contexts. This pattern allows you to directly set and get NSArray objects into the core data object. The basic principle behind it is here: https://coderwall.com/p/mx_wmq

首先,创建具有可转换属性(您的数组)和与之配套的数据属性的模型.

First, create the model with a transformable attribute (your array) and a data attribute to go with it.

接下来,在折线对象上创建一个类别.

Next, create a category on the polyline object.

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

You should now have these items in your file browser

折线+TransformableAttributes.h

Polyline+TransformableAttributes.h

#import "Polyline.h"

@interface Polyline (TransformableAttributes)

#pragma mark transformables

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

@end

折线+TransformableAttributes.m

Polyline+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

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);
    }
}

请告诉我它是否适合您.如果需要,我会更新我的答案,以便它有用.我不记得我最初在哪里发现这个模式,但它真的很有帮助并且得到了高度赞扬

Please let me know if it works for you. I'll update my answer if needed, so that it can be useful. I can't remember where I originally found this pattern but it was a really helpful and highly upvoted

编辑 1:添加了 GPS 视图

Edit 1: Added a gps view

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

Here is a new controller I added:

GPSViewController.h:

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;

我的 GPSViewController.m 中的代码:

The code in my GPSViewController.m:

初始化数组以存储我的坐标.

Initialize the array to store my coordinates.

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    _locationsArray = [NSMutableArray array];
}

当您单击 GPS 按钮时,它会转到此处.locationManager 是类的实例变量.

When you click the GPS button, it goes here. locationManager is an instance variable of the class.

-(IBAction)didClickStartGPS:(id)sender {
    locationManager = [[CLLocationManager alloc] init];
    [locationManager setDelegate:self];
    [locationManager startUpdatingLocation];
}

这会将坐标保存到折线中并保留它.注意:对于这段代码,我没有做任何特定的搜索描述符,所以如果你多次点击保存,你会在核心数据中得到一堆折线,而且每次可能只会加载第一个.如果将某个 ID 或日期添加到折线对象中,则可以执行诸如在它们中搜索特定 ID 或日期之类的操作.

This saves the coordinates into a polyline and persists it. Note: with this code, I don't do any specific search descriptors, so if you click save multiple times, you'll get a bunch of polylines in your core data, and it'll probably only load the first one each time. You can do stuff like search through them for a certain id or date if you add that to the polyline object.

-(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);
    }
}

这将从核心数据加载第一个折线对象并将其转换为您的 _locationArray 的 CLLocations.我不会对你从他们那里得到的 CLLocationCoordinate2D 做任何事情.

This loads the first polyline object from core data and converts it into your _locationArray of CLLocations. I don't do anything with the CLLocationCoordinate2D you can get from them.

-(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:@"Polyline"];
    NSError *error;
    id results = [appDelegate.managedObjectContext executeFetchRequest:request error:&error];

    if ([results count]) {
        polyLine = (Polyline *)(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];
    }
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    CLLocation *currentLocation = [locations lastObject];
    CLLocationDegrees latitude = currentLocation.coordinate.latitude;
    CLLocationDegrees longitude = currentLocation.coordinate.longitude;
    CLLocationCoordinate2D locationCoordinates = CLLocationCoordinate2DMake(latitude, longitude);

    //store latest location in stored track array;
    [_locationsArray addObject:currentLocation];
}

此代码在我的github上更新:

This code is updated on my github:

github.com/bobbyren/StackOverflowTest.git

github.com/bobbyren/StackOverflowTest.git

为每条折线添加一条新的 MKPolyline:

To add a new MKPolyline for each Polyline:

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];

这篇关于你如何将 NSMutable Array 中的数据存储在 Core Data 中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆