使用NSMutableArray保存和加载MapAnnotation引脚 [英] Save and Load MapAnnotation pins using NSMutableArray

查看:70
本文介绍了使用NSMutableArray保存和加载MapAnnotation引脚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要有关MapAnnotation代码的帮助.我想保存地图图钉,以便用户可以返回地图并查看他/她放置的图钉.

I need help with my MapAnnotation codes. I want to save map pins so that the user can come back to the map and see the ones he/she has placed.

但是,此代码在视图加载时不显示引脚.

However this code does not show the pins when the view loads.

添加和保存密码的代码:

Code for adding and saving pins:

- (void)addPinToMap:(UIGestureRecognizer *)gestureRecognizer
{

if (gestureRecognizer.state != UIGestureRecognizerStateBegan)
    return;



CGPoint touchPoint = [gestureRecognizer locationInView:self.mapView];
CLLocationCoordinate2D touchMapCoordinate =
[self.mapView convertPoint:touchPoint toCoordinateFromView:self.mapView];

 //NSMutableArray *pincoords = (NSMutableArray *)[[NSUserDefaults standardUserDefaults] objectForKey:@"saveCoords"];

NSMutableDictionary *pindict;

NSUserDefaults *def = [NSUserDefaults standardUserDefaults];

NSMutableArray *pincoords = [def objectForKey:@"saveCoords"];


CLLocationCoordinate2D coordinates;

coordinates.latitude = touchMapCoordinate.latitude;
coordinates.longitude = touchMapCoordinate.longitude;

NSNumber* latDegrees = [NSNumber numberWithFloat:touchMapCoordinate.latitude];
NSNumber* longDegrees = [NSNumber numberWithFloat:touchMapCoordinate.longitude];



 [pindict setObject:latDegrees forKey:@"pinlat"];
  [pindict setObject:longDegrees forKey:@"pinlong"];








 MapAnnotation *toAdd = [[MapAnnotation alloc]init];


toAdd.coordinate = coordinates;
toAdd.title = @"Svampe Spot";

[self.mapView addAnnotation:toAdd];


[pincoords addObject:pindict];

[def synchronize];


}

我的加载代码:

- (void)viewDidLoad
{

 [super viewDidLoad];


   NSUserDefaults *def = [NSUserDefaults standardUserDefaults];

   NSMutableArray *pincoords = [def objectForKey:@"saveCoords"];

   for (NSDictionary *pindict in pincoords) {

     CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake([[pindict objectForKey:@"pinlat"] floatValue], [[pindict objectForKey:@"pinlong"] floatValue]);

    MapAnnotation *mapPin = [[MapAnnotation alloc]init];





    mapPin.coordinate = coordinate;
    mapPin.title = @"Svampe Spot";

    [self.mapView addAnnotation:mapPin];
    [def synchronize];


    [def synchronize];

 }

}

一个解决方案将不胜感激!

A solution would be much appreciated!!

删除特定注释的代码:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)mapViewpin
calloutAccessoryControlTapped:(UIControl *)control {


NSUserDefaults *def = [NSUserDefaults standardUserDefaults];

NSMutableArray *pincoords = [def objectForKey:@"saveCoords"];

for (NSDictionary *pindict in pincoords) {

 CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(
                                                               [[pindict objectForKey:@"pinlat"] doubleValue],
                                                               [[pindict objectForKey:@"pinlong"] doubleValue]);

 MapAnnotation *mapPin = mapViewpin.annotation;

 mapPin.coordinate =coordinate;

 [self.mapView removeAnnotation:mapPin];
 [def removeObjectForKey:@"saveCoords"];

 [def synchronize];
}


}

这将全部删除.如何针对点击了谁的注解按钮特定它?

This deletes them all. How do i make it specific for the annotation whos button is tapped?

推荐答案

沃尔克的答案确实指出了一个重要问题:

Volker's answer does point out one important issue:

用户第一次添加引脚时,用户默认值将不会保存任何数组,因此pinCoords将为nil.因此,对数组的addObject调用将无济于事.如果是nil,则需要分配一个空数组来处理这种情况,以便向其添加对象.

The first time the user adds a pin, there will be no array already saved in the user defaults so pinCoords will be nil. Therefore, the addObject calls on the array will do nothing. You need to handle this case by allocating an empty array if it's nil so you can add objects to it.


但是,addPinToMap:中仍然存在其他问题,即使修复了上述问题,该问题也仍将阻止代码工作:


However, there are still other issues in addPinToMap: that will prevent the code from working even after fixing the above:

  1. 已声明pindict变量 ,但从未已分配.当您在其上调用setObject:forKey:时,这将导致崩溃或不执行任何操作.您需要分配pindict变量.
  2. 对于NSUserDefaultsobjectForKey:将返回不可变对象.这意味着即使将pincoords声明为NSMutableArrayobjectForKey:仍将返回NSArray(如果它在用户默认值中找到了键的值).因此,由于无法将对象添加到NSArray,因此addObject调用将再次失败(这次是崩溃).您需要做的是获取objectForKey:的结果,并通过调用mutableCopy对其进行可变版本.
  3. 将新坐标添加到pinCoords后,代码不会将更新后的数组保存回用户默认值.它只是调用synchronize.在调用synchronize之前,您需要通过调用setObject:forKey:将数组实际保存为用户默认设置.
  1. The pindict variable is declared but never allocated. This will either lead to a crash when you call setObject:forKey: on it or do nothing. You need to allocate the pindict variable.
  2. With NSUserDefaults, objectForKey: will return an immutable object. That means even though pincoords is declared as an NSMutableArray, objectForKey: will return an NSArray (if it finds a value for the key in user defaults). Therefore, the addObject calls will again fail (this time with a crash) since you can't add objects to an NSArray. What you need to do is take the result of objectForKey: and make a mutable version of it by calling mutableCopy.
  3. After adding the new coordinates to pinCoords, the code does not save the updated array back to user defaults. It just calls synchronize. Before calling synchronize, you need to actually save the array to user defaults by calling setObject:forKey:.

进行上述所有更改后,代码应该可以正常工作.

After making all the above changes, the code should work.


我还建议再进行两项更改以改进代码(尽管这些并不能阻止其工作):


I also recommend two more changes to improve the code (though these aren't preventing it from working):

  1. 将坐标另存为double,而不是将其另存为float值.核心位置中的纬度和经度实际上是double类型(CLLocationDegrees实际上是双精度).您还将获得更好的精度.因此,在addPinToMap:中,使用numberWithDouble代替numberWithFloat;在viewDidLoad中,使用doubleValue代替floatValue.
  2. viewDidLoadfor循环内,您两次调用synchronize.这些调用毫无意义-将其删除.
  1. Instead of saving the coordinates as float values, save them as double. The latitude and longitude in Core Location are actually of type double (CLLocationDegrees is actually a double). You'll also get better precision. So in addPinToMap:, use numberWithDouble instead of numberWithFloat and in viewDidLoad, use doubleValue instead of floatValue.
  2. In viewDidLoad, inside the for loop, you are calling synchronize twice. These calls are pointless -- remove them.


addPinToMap:中最终的,更新的代码是这样的:


The final, updated code in addPinToMap: would be this:

- (void)addPinToMap:(UIGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state != UIGestureRecognizerStateBegan)
        return;

    CGPoint touchPoint = [gestureRecognizer locationInView:self.mapView];
    CLLocationCoordinate2D touchMapCoordinate = [self.mapView convertPoint:touchPoint toCoordinateFromView:self.mapView];

    NSMutableDictionary *pindict = [NSMutableDictionary dictionary];

    NSUserDefaults *def = [NSUserDefaults standardUserDefaults];

    NSMutableArray *pincoords = [[def objectForKey:@"saveCoords"] mutableCopy];
    if (pincoords == nil)
    {
        pincoords = [NSMutableArray array];
    }

    CLLocationCoordinate2D coordinates;

    coordinates.latitude = touchMapCoordinate.latitude;
    coordinates.longitude = touchMapCoordinate.longitude;

    NSNumber* latDegrees = [NSNumber numberWithDouble:touchMapCoordinate.latitude];
    NSNumber* longDegrees = [NSNumber numberWithDouble:touchMapCoordinate.longitude];

    [pindict setObject:latDegrees forKey:@"pinlat"];
    [pindict setObject:longDegrees forKey:@"pinlong"];

    MapAnnotation *toAdd = [[MapAnnotation alloc]init];

    toAdd.coordinate = coordinates;
    toAdd.title = @"Svampe Spot";

    [self.mapView addAnnotation:toAdd];

    [pincoords addObject:pindict];

    [def setObject:pincoords forKey:@"saveCoords"];

    [def synchronize];
}

viewDidLoad中更新的for循环如下所示:

The updated for loop in viewDidLoad would be like this:

for (NSDictionary *pindict in pincoords) {

    CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(
        [[pindict objectForKey:@"pinlat"] doubleValue], 
        [[pindict objectForKey:@"pinlong"] doubleValue]);

    MapAnnotation *mapPin = [[MapAnnotation alloc]init];

    mapPin.coordinate = coordinate;
    mapPin.title = @"Svampe Spot";

    [self.map addAnnotation:mapPin];
}

这篇关于使用NSMutableArray保存和加载MapAnnotation引脚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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