使用NSMutableArray保存并加载MapAnnotation引脚

我需要帮助我的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]; } } 

解决scheme将不胜感激!

删除特定注释的代码:

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

这将全部删除。 我如何使它特定于注释whosbutton被点击?

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

用户第一次添加一个pin时,将不会有用户默认保存的数组,所以pinCoords将是nil 。 因此,数组上的addObject调用将不会执行任何操作。 你需要通过分配一个空数组来处理这种情况,如果它是nil所以你可以添加对象。

但是,在addPinToMap:中还有其他的问题addPinToMap:即使修改了上面的代码,也会阻止代码工作:

  1. pindictvariables被声明,但从来没有分配 。 这会导致崩溃,当你调用setObject:forKey:或者什么也不做。 你需要分配pindictvariables。
  2. 使用NSUserDefaultsobjectForKey:将返回一个不可变的对象。 这意味着,即使pincoords被声明为一个NSMutableArrayobjectForKey:将返回一个NSArray (如果它在用户默认情况下为键find一个值)。 因此, addObject调用将再次失败(这次是崩溃),因为您无法将对象添加到NSArray 。 你需要做的就是获取objectForKey:的结果objectForKey:并通过调用mutableCopy创build一个可变的版本。
  3. 在将新坐标添加到pinCoords ,代码不会将更新的数组保存回用户默认值 。 它只是调用synchronize 。 在调用synchronize之前,你需要通过调用setObject:forKey:来将这个数组实际保存为用户的默认值。

完成上述所有更改后,代码应该可以工作。

我还推荐两个更改来改进代码(尽pipe这些更改并不妨碍它的工作):

  1. 不要将坐标保存为float值,而应将其保存为double 。 核心位置的经纬度实际上是doubletypes( CLLocationDegrees实际上是双CLLocationDegrees )。 你也会得到更好的精度。 所以在addPinToMap: ,使用numberWithDouble而不是numberWithFloat并在viewDidLoad ,使用doubleValue而不是floatValue
  2. viewDidLoad ,在for循环中,您正在调用两次synchronize 。 这些电话是毫无意义的 – 删除它们。

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

viewDidLoad更新for循环将是这样的:

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

最初,用户des不包含该键的可变数组。 所以当访问键的对象时,检查是否返回非零,否则创build一个新的可变数组来填充点。

要解决您的问题,只需移除其中一个标记,Anna就是正确的,您必须添加一条类似于您的创build方法的标识符以查找:

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