使用NSMutableArray保存并加载MapAnnotation引脚

时间:2014-01-30 21:45:16

标签: ios nsmutablearray mkmapview nsuserdefaults mkannotation

我需要MapAnnotation代码的帮助。我想保存地图别针,以便用户可以回到地图并查看他/她放置的地图。

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

添加和保存引脚的代码:

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

 }

}

非常感谢解决方案!!

删除特定注释的代码:

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


}

这将删除所有内容。如何使其特定于按钮被点击的注释?

3 个答案:

答案 0 :(得分:2)

Volker的回答确实指出了一个重要问题:

用户首次添加图钉时,用户默认设置中不会保存任何阵列,因此pinCoords将为nil。因此,对数组的addObject调用将不执行任何操作。你需要通过分配一个空数组nil来处理这种情况,这样你就可以向它添加对象了。


但是,addPinToMap:中仍有其他问题会阻止代码在修复上述内容后仍然有效:

  1. pindict变量已声明但从未已分配。当您在其上调用setObject:forKey:或什么都不做时,这会导致崩溃。您需要分配pindict变量。
  2. 使用NSUserDefaultsobjectForKey:将返回不可变对象。这意味着即使pincoords被声明为NSMutableArrayobjectForKey:也会返回NSArray(如果它在用户默认值中找到键的值)。因此,addObject调用将再次失败(这次是崩溃),因为您无法将对象添加到NSArray。您需要做的是获取objectForKey:的结果并通过调用mutableCopy制作一个可变版本。
  3. 将新坐标添加到pinCoords后,代码不会将更新后的数组保存回用户默认值。它只是调用synchronize。在调用synchronize之前,您需要通过调用setObject:forKey:将数组实际保存为用户默认值。
  4. 完成上述所有更改后,代码应该可以正常工作。


    我还建议另外两个更改来改进代码(虽然这些不会阻止它工作):

    1. 不将坐标保存为float值,而是将其保存为double。核心位置的纬度和经度实际上是double类型(CLLocationDegrees实际上是双倍)。你也会获得更好的精确度。因此,在addPinToMap:中,使用numberWithDouble代替numberWithFloat,使用viewDidLoad,使用doubleValue代替floatValue
    2. viewDidLoad for循环内,您正在调用synchronize两次。这些调用毫无意义 - 删除它们。

    3. addPinToMap:中的最终更新代码为:

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

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

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

答案 1 :(得分:0)

最初用户des不包含密钥的可变数组。因此,当访问密钥的对象时,请检查是否返回了非nil,否则创建一个新的可变数组来填充这些点。

答案 2 :(得分:0)

要解决仅删除其中一个标记的问题,Anna是正确的,您必须在创建方法中添加类似这样的行,以便查找标识符:

[pindict setObject:NAME_OF_YOUR_MARKER_TITLE forKey:@"name"];

然后执行以下操作以查看是否存在,将其从位置数组中删除,然后保存数据:

 myMapAnnotation *selectedAnnotation = mapViewpin.annotation;

    //Iterate through the location markers
    for (int i = 0; i<pincoords.count; i++) {

        if ([pincoords[i] containsObject: selectedAnnotation.title]) {

            //Create a new mutable array to work with
            NSMutableArray *pincoords = [[def objectForKey:@"saveCoords"]mutableCopy];

            //Remove the marker
            [pincoords removeObjectAtIndex:i];
            [self.mapView removeAnnotation:selectedAnnotation];

            //Update the data
            [def setObject:pincoords forKey:@"saveCoords"];
        }

        //Sync outside the loop
        [def synchronize];

    }