使用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:
即使修改了上面的代码,也会阻止代码工作:
-
pindict
variables被声明,但从来没有分配 。 这会导致崩溃,当你调用setObject:forKey:
或者什么也不做。 你需要分配pindict
variables。 - 使用
NSUserDefaults
,objectForKey:
将返回一个不可变的对象。 这意味着,即使pincoords
被声明为一个NSMutableArray
,objectForKey:
将返回一个NSArray
(如果它在用户默认情况下为键find一个值)。 因此,addObject
调用将再次失败(这次是崩溃),因为您无法将对象添加到NSArray
。 你需要做的就是获取objectForKey:
的结果objectForKey:
并通过调用mutableCopy
创build一个可变的版本。 - 在将新坐标添加到
pinCoords
,代码不会将更新的数组保存回用户默认值 。 它只是调用synchronize
。 在调用synchronize
之前,你需要通过调用setObject:forKey:
来将这个数组实际保存为用户的默认值。
完成上述所有更改后,代码应该可以工作。
我还推荐两个更改来改进代码(尽pipe这些更改并不妨碍它的工作):
- 不要将坐标保存为
float
值,而应将其保存为double
。 核心位置的经纬度实际上是double
types(CLLocationDegrees
实际上是双CLLocationDegrees
)。 你也会得到更好的精度。 所以在addPinToMap:
,使用numberWithDouble
而不是numberWithFloat
并在viewDidLoad
,使用doubleValue
而不是floatValue
。 - 在
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]; }