我需要有关 MapAnnotation 代码的帮助。我想保存 map 图钉,以便用户可以返回 map 并查看他/她放置的图钉。
但是,此代码在 View 加载时不显示引脚。
添加和保存图钉的代码:
- (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];
}
}
这会将它们全部删除。我如何使其特定于点击了按钮的注释?
最佳答案
Volker 的回答确实指出了一个重要问题:
用户第一次添加 pin 时,用户默认值中将没有已保存的数组,因此 pinCoords
将为 nil
。因此,对数组的 addObject
调用不会执行任何操作。如果它是 nil
,您需要通过分配一个空数组来处理这种情况,以便您可以向其中添加对象。
但是,addPinToMap:
中仍然存在其他问题,即使在修复上述问题后代码仍无法正常工作:
pindict
变量已声明,但从未分配。当您对其调用setObject:forKey:
时,这将导致崩溃或什么都不做。您需要分配pindict
变量。- 使用
NSUserDefaults
,objectForKey:
将返回一个不可变 对象。这意味着即使pincoords
被声明为NSMutableArray
,objectForKey:
也会返回一个NSArray
(如果它找到一个用户默认值中键的值)。因此,addObject
调用将再次失败(这次是崩溃),因为您无法将对象添加到NSArray
。您需要做的是获取objectForKey:
的结果,并通过调用mutableCopy
制作它的可变版本。 - 将新坐标添加到
pinCoords
后,代码不会将更新后的数组保存回用户默认值。它只是调用同步
。在调用synchronize
之前,您需要通过调用setObject:forKey:
将数组实际保存为用户默认值。
进行上述所有更改后,代码应该可以工作了。
我还建议再进行两处更改以改进代码(尽管这些不会阻止它正常工作):
- 不要将坐标保存为
float
值,而是将它们保存为double
。 Core Location中的纬度和经度实际上是double
类型(CLLocationDegrees
实际上是double)。您还将获得更好的精度。所以在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];
}
关于ios - 使用 NSMutableArray 保存和加载 MapAnnotation 引脚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21468053/