gpt4 book ai didi

ios - 带本地搜索的 MapView

转载 作者:行者123 更新时间:2023-11-29 10:57:13 24 4
gpt4 key购买 nike

我有一个关于在 Apple map 中进行本地搜索的问题,我已经在我的应用程序中实现了这一点。该应用程序应向用户显示他周围的“超市”在哪里。我的 mapView 还显示了用户的当前位置,但我真的不知道我应该如何使用市场位置的结果来做到这一点。也许苹果为此提供了解决方案/建议。提前致谢。

The results (supermarkets) should be displayed as in this picture

结果(超市)应如图所示显示。

更新:该功能完美运行,但是否也可以使这些图钉可点击以显示有关此位置的信息表,如下图所示?

enter image description here enter image description here

更新 2:我对这个 map 实现非常着迷,所以我想知道是否也可以获取有关您当前位置的信息(如下面的屏幕截图所示)。 enter image description here

最佳答案

在 iOS 6.1 及更高版本中,您可以使用 MKLocalSearch ,为每个 MKMapItem 添加注释你找到的对象。

MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = @"supermarket";
request.region = mapView.region;

MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];

[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
for (MKMapItem *item in response.mapItems)
{
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
annotation.coordinate = item.placemark.coordinate;
annotation.title = item.name;
annotation.subtitle = item.placemark.title;
[mapView addAnnotation:annotation];
}
}];

如果您想要标注上的左右附件,您应该实现一个添加这些附件的 viewForAnnotation(当然,要实现这一点,您必须将 Controller 定义为delegate 为您的 MKMapView:

typedef enum : NSInteger
{
kCallOutAccessoryRight = 1,
kCallOutAccessoryLeft
} CallOutAccessoryType;

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;

static NSString *identifier = @"customAnnotationView";

MKAnnotationView *annotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];

if (annotationView == nil)
{
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.canShowCallout = YES;

annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.rightCalloutAccessoryView.tag = kCallOutAccessoryRight;

annotationView.leftCalloutAccessoryView = ...; // whatever you want for the left button
annotationView.leftCalloutAccessoryView.tag = kCallOutAccessoryLeft;
}
else
{
annotationView.annotation = annotation;
}

return annotationView;
}

而且,您可能想要响应用户点击这些标注:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
if (control.tag == kCallOutAccessoryRight)
{
NSLog(@"Present info sheet for %@ here", [view.annotation title]);
}
else if (control.tag == kCallOutAccessoryLeft)
{
NSLog(@"Do whatever you want if left accessory tapped");
}
}

您询问了如何向用户显示方向。是的,您可以通过将 MKMapItem 传递给 openMapsWithItems 来做到这一点。但这假定您从本地搜索中保存了 MKMapItem。为此,您要创建自定义注释。例如:

//  MapItemAnnotation.h

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface MapItemAnnotation : NSObject <MKAnnotation>

@property (nonatomic, strong, readonly) MKMapItem *item;

- (id)initWithMapItem:(MKMapItem *)item;
- (NSString *)title;
- (NSString *)subtitle;
- (CLLocationCoordinate2D)coordinate;

@end

//  MapItemAnnotation.m

#import "MapItemAnnotation.h"

@implementation MapItemAnnotation

- (id)initWithMapItem:(MKMapItem *)item
{
self = [super init];
if (self) {
_item = item;
}
return self;
}

- (NSString *)title
{
return _item.name;
}

- (NSString *)subtitle
{
return _item.placemark.title;
}

- (CLLocationCoordinate2D)coordinate
{
return _item.placemark.coordinate;
}

@end

完成后,向 map 添加注释会稍微简化一些:

[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
for (MKMapItem *item in response.mapItems)
{
MapItemAnnotation *annotation = [[MapItemAnnotation alloc] initWithMapItem:item];
[mapView addAnnotation:annotation];
}
}];

但是,现在,您的左侧标注配件可以轻松地在 Apple map 中启动方向:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
if (control.tag == kCallOutAccessoryRight)
{
NSLog(@"Present info sheet for %@ here", [view.annotation title]);
}
else if (control.tag == kCallOutAccessoryLeft)
{
// request directions from Apple Maps

MapItemAnnotation *annotation = view.annotation;
NSAssert([annotation isKindOfClass:[MapItemAnnotation class]], @"Annotation should be MapItemAnnotation: %@", annotation);

[annotation.item openInMapsWithLaunchOptions:@{MKLaunchOptionsMapCenterKey : [NSValue valueWithMKCoordinate:mapView.region.center],
MKLaunchOptionsMapSpanKey : [NSValue valueWithMKCoordinateSpan:mapView.region.span],
MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving}];
}
}

关于更新用户位置描述,你可以定义一个didUpdateUserLocation方法(即每次用户位置发生变化时, map View 都会调用此 MKMapViewDelegate 方法)。看起来您想更新用户位置的副标题:

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
[self updateSubtitleForUserLocation:userLocation];
}

这将调用此方法进行反向地理编码并相应地更新副标题:

- (void)updateSubtitleForUserLocation:(MKUserLocation *)userLocation
{
if ([self.geocoder isGeocoding])
[self.geocoder cancelGeocode];

[self.geocoder reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray *placemarks, NSError *error) {
MKPlacemark *placemark = placemarks[0];
userLocation.subtitle = placemark.name;
}];
}

显然,您需要一个类属性:

@property (nonatomic, strong) CLGeocoder *geocoder;

你需要实例化它,例如viewDidLoad 可以:

self.geocoder = [[CLGeocoder alloc] init];

如果用户的位置变化超过 x 米,我可能会对此进行一些改进以仅执行反向地理编码(您不想执行太多反向地理编码请求;您将杀死用户的电池),但希望这能说明这个想法。

关于ios - 带本地搜索的 MapView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17682834/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com