MKMapView 不移动和缩放到搜索结果
Posted
技术标签:
【中文标题】MKMapView 不移动和缩放到搜索结果【英文标题】:MKMapView does not move and zoom to search results 【发布时间】:2014-07-18 10:49:14 【问题描述】:我正在我的 MKMapView 中实现搜索,我遇到了两个问题:
-
当我执行搜索时,位置会出现在结果中,并且地图会在我开始移动到目的地后移动到找到的位置仅。当搜索结果超出视图范围时,就会发生这种情况。如果它们在地图视图范围内或靠近,那很好。
它总是从一个搜索结果“跳跃”到另一个或到用户的位置。我不希望它有这样的行为。
我已经尝试了几件事,我想问题出在:didAddAnnotationViews
:
[self.locationManager stopUpdatingLocation];
MKAnnotationView *annotationView = [views objectAtIndex:0];
NSLog(@"_Here_ %@", [views description]);
id<MKAnnotation> mp = [annotationView annotation];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([mp coordinate], 250, 250);
[mv setRegion:region animated:YES];
[self.mapView selectAnnotation:mp animated:YES];
不过,我也认为问题出在didUpdateToLocation
,所以我在第一个 pin 被丢弃后禁用更新(通过搜索或点击):
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
double miles = 0.3;
double scalingFactor =
ABS( cos(2 * M_PI * newLocation.coordinate.latitude /360.0) );
MKCoordinateSpan span;
span.latitudeDelta = miles/69.0;
span.longitudeDelta = miles/( scalingFactor*69.0 );
MKCoordinateRegion region;
region.span = span;
region.center = newLocation.coordinate;
[self.mapView setRegion:region animated:YES];
self.mapView.showsUserLocation = YES;
最后,搜索方法:
-(void)searchBarSearchButtonClicked:(UISearchBar *)theSearchBar
MKLocalSearchRequest *searchRequest = [[MKLocalSearchRequest alloc] init];
[searchRequest setNaturalLanguageQuery:theSearchBar.text];
searchRequest.region = MKCoordinateRegionMakeWithDistance(self.mapView.userLocation.coordinate, 1000, 1000);
MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:searchRequest];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error)
if (!error)
NSMutableArray *annotations = [NSMutableArray array];
[response.mapItems enumerateObjectsUsingBlock:^(MKMapItem *item, NSUInteger idx, BOOL *stop)
for (id<MKAnnotation>annotation in self.mapView.annotations)
if (annotation.coordinate.latitude == item.placemark.coordinate.latitude &&
annotation.coordinate.longitude == item.placemark.coordinate.longitude)
return;
MKPointAnnotation *addAnnotation = [[MKPointAnnotation alloc] init];
addAnnotation.title = [item.placemark.addressDictionary objectForKey:@"Street"];
addAnnotation.coordinate = item.placemark.coordinate;
[annotations addObject:addAnnotation];
];
for (id<MKAnnotation>annotation in self.mapView.annotations)
[self.mapView removeAnnotation:annotation];
[self.mapView addAnnotations:annotations];
else
NSLog(@"Search Request Error: %@", [error localizedDescription]);
];
//Hide the keyboard.
[self.searchBar resignFirstResponder];
我的目标是创建一个 MapView,用户可以在其中通过点击或搜索固定位置,并且显然可以查看搜索结果。
【问题讨论】:
【参考方案1】:对于第一个问题:
当我执行搜索时,位置出现在结果中并且地图移动到 只有在我开始移动到目的地之后才找到位置。这 当搜索结果超出视图范围时发生。如果他们 在地图视图范围内或附近都可以。
发生这种情况是因为您将地图移动到在didAddAnnotationViews
委托方法中找到的注释(至少是第一个)。
但是只有当注释在可见区域时才会调用该委托方法。如果注释被添加到地图但它不在可见区域(还),viewForAnnotation
将不会被调用,因此didAddAnnotationViews
将不会被调用。
然后,当您手动移动地图时,添加的注释开始进入可见区域,然后调用委托方法,地图突然跳转到其中一个注释。
不要在didAddAnnotationViews
委托方法中调用setRegion
。
有时,这样做还会导致viewForAnnotation
和didAddAnnotationViews
调用的无限循环,因为当区域更改时,它会导致看到以前没有的其他注释,因此viewForAnnotation
被调用并然后didAddAnnotationViews
被调用,以此类推。
相反,在searchBarSearchButtonClicked:
方法中调用addAnnotations:
(或者更好,只需调用showAnnotations:
)之后立即设置区域。
我还会从didAddAnnotationViews
中删除对stopUpdatingLocation
的调用。如果您将地图的 showsUserLocation
设置为 YES
,您可能甚至根本不需要位置管理器。
对于第二个问题:
它总是从一个搜索结果“跳跃”到另一个搜索结果或 用户的位置。我不希望它有这样的行为。
这部分是由于在didAddAnnotationViews
中调用了setRegion
,还因为在didUpdateToLocation
中调用了setRegion
。
因此,由于第一个问题所描述的原因,两个委托方法和用户的手动移动相互争斗,地图最终跳来跳去。
不要在 didUpdateToLocation
方法中调用 setRegion
(或者,通过在 BOOL 中跟踪是否已缩放到用户位置与否)。
不影响行为,但在didUpdateToLocation
中将showsUserLocation
设置为YES
没有意义。为什么不在viewDidLoad
中设置它或在storyboard/xib 中打开它?
此外,无需像那样手动计算区域跨度(最好让 MapKit 为您完成这项工作)。只需将英里转换为米并致电MKCoordinateRegionMakeWithDistance
。
【讨论】:
如果它对您有用,您可以将 selectAnnotation 保留在该委托方法中。到目前为止显示的代码应该没有问题。以上是关于MKMapView 不移动和缩放到搜索结果的主要内容,如果未能解决你的问题,请参考以下文章
防止 MKMapView 不断地重新缩放和重新居中到用户位置
SwiftUI 上的按钮点击调用 MKMapView.setRegion