MKMapView的基本使用

iOS系统自带的MapView基本使用

感觉用第三方地图只需要根据现成的文档走就基本上很轻松实现,所以想自己使用一下系统自带的方法实现一些地图的基本功能,网上查阅了一下实现了基本功能,和初学者共同进步

主要功能

  • 定位到用户当前位置
  • 显示 附近位置
  • 长按地图选点
  • 手动搜索位置

效果图如下:

map.gif

1 定位 当前用户位置

首先得在infoplist文件里面添加NSLocationWhenInUseUsageDescription字段来让系统提示授权应用定位服务

其次就是判断是否有定位服务代码了

- (void)viewDidLoad {
    [super viewDidLoad];
    
   
    self.locationManager=[[CLLocationManager alloc]init];;
   
    //判断当前设备定位服务是否打开
    if (![CLLocationManager locationServicesEnabled]) {
        NSLog(@"设备尚未打开定位服务");
    }
    
    //判断当前设备版本大于iOS8以后的话执行里面的方法
    if ([UIDevice currentDevice].systemVersion.floatValue >=8.0) {
        //持续授权
        // [locationManager requestAlwaysAuthorization];
        //当用户使用的时候授权
        [self.locationManager requestWhenInUseAuthorization];
    }
    if ([CLLocationManager authorizationStatus] ==kCLAuthorizationStatusDenied) {
        
        NSString *message = @"您的手机目前未开启定位服务,如欲开启定位服务,请至设定开启定位服务功能";
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"无法定位" message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil];
        [alertView show];
        
    }
    //请求授权
    // [locationManager requestWhenInUseAuthorization];
    
    /*
     MKUserTrackingModeNone  不进行用户位置跟踪
     MKUserTrackingModeFollow  跟踪用户的位置变化
     MKUserTrackingModeFollowWithHeading  跟踪用户位置和方向变化
     */
    //设置用户的跟踪模式
    self.mapView.userTrackingMode=MKUserTrackingModeFollow;
    /*
     MKMapTypeStandard  标准地图
     MKMapTypeSatellite    卫星地图
     MKMapTypeHybrid      鸟瞰地图
     MKMapTypeSatelliteFlyover
     MKMapTypeHybridFlyover
     */
    self.mapView.mapType=MKMapTypeStandard;
    //实时显示交通路况
    self.mapView.showsTraffic=NO;
    //设置代理
    self.mapView.delegate=self;
    [self initMapView];
    [self initSearch];
    [self initTableView];
    
    
}

其次是初始化地图显示用户当前位置

pragma mark - 初始化
- (void)initMapView
{
    _mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0,54, SCREEN_WIDTH, SCREEN_HEIGHT - CELL_HEIGHT*CELL_COUNT)];
    _mapView.delegate = self;
    // 不显示罗盘
    _mapView.showsCompass = NO;
    // 不显示比例尺
    _mapView.showsScale = NO;
    
    MKCoordinateSpan span=MKCoordinateSpanMake(0.021251, 0.016093);
    
    [self.mapView setRegion:MKCoordinateRegionMake(self.mapView.userLocation.coordinate, span) animated:YES];
    // 开启定位
    _mapView.showsUserLocation = YES;
    [self.view addSubview:_mapView];
  
}
/**
 *  跟踪到用户位置时会调用该方法
 *  @param mapView   地图
 *  @param userLocation 大头针模型
 */
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
    
    if (userLocation&& !_isFirstLocated) {
        //创建编码对象
        CLGeocoder *geocoder=[[CLGeocoder alloc]init];
        //反地理编码
        [geocoder reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) {
            if (error!=nil || placemarks.count==0) {
                return ;
            }
            //获取地标
            CLPlacemark *placemark=[placemarks firstObject];
            //设置标题
            userLocation.title=placemark.locality;
            //设置子标题
            userLocation.subtitle=placemark.name;
            _dangQiang = placemark;
            [self fetchNearbyInfo:userLocation.location.coordinate.latitude andT:userLocation.location.coordinate.longitude];
        }];
        [_mapView setCenterCoordinate:CLLocationCoordinate2DMake(userLocation.location.coordinate.latitude, userLocation.location.coordinate.longitude)];
        _isFirstLocated = YES;
        
    }
    
}

2 显示附近位置

根据传入的坐标显示附近的位置,这里要说下系统一次性只会返回固定十个数据的数组,要说明的一点是里面有个requst.naturalLanguageQuery = @"place"这句话 传的字段是place这个字段系统会返回附近几个地址你可以传任何地面建筑类型的英文进去都可以被识别搜索比如医院的英文单词hospital系统只会返回附近的医院,见如下代码:

- (void)fetchNearbyInfo:(CLLocationDegrees )latitude andT:(CLLocationDegrees )longitude

{
    
    CLLocationCoordinate2D location=CLLocationCoordinate2DMake(latitude, longitude);
    
    MKCoordinateRegion region=MKCoordinateRegionMakeWithDistance(location, 1 ,1 );
    
    MKLocalSearchRequest *requst = [[MKLocalSearchRequest alloc] init];
    requst.region = region;
    requst.naturalLanguageQuery = @"place"; //想要的信息
    MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:requst];
    [self.dataRrray removeAllObjects];
    [localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error){
        if (!error)
        {
          
            for (MKMapItem *map in response.mapItems) {
                NSLog(@"%@",map.name);
            }
            [self.dataRrray addObjectsFromArray:response.mapItems];
            [self.tableView reloadData];
            //
        }
        else
        {
            //
        }
    }];
}

3 长按地图选点

说白了就是在MapVIew上面加一个长按手势添加大头针,为了避免篇幅过程该功能就不贴代码描述详情可以见文章末尾Demo

4 手动搜索地址

这个功能还是比较常见的的嘿嘿,我也是网上参考别人的实现的,各位看官看看以下代码都差不多就会了,就是调用一个方法的事

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    CLGeocoder *geocoder=[[CLGeocoder alloc]init];
    //判断是否为空
    if (searchText.length ==0) {
        return;
    }
    [self.searchResultArray removeAllObjects];
    [geocoder geocodeAddressString:searchText completionHandler:^(NSArray * _Nullable placemarks, NSError * _Nullable error) {
        if (error!=nil || placemarks.count==0) {
            return ;
        }
        //创建placemark对象
        
        
        self.searchResultArray = [[NSMutableArray alloc]initWithArray:placemarks];
        //CLPlacemark *placemark=[self.searchResultArray firstObject];
        [self.searchDisplayController.searchResultsTableView reloadData];
 
}

5 MapView性能优化问题

相信很多初学者和我一样适用系统自带的地图时占用内存会暴涨,我做完上述功能也只网上查了不少资料有些大神说把地图绘制成图片显示等等我看了有点蒙蔽,找到了两个简单的优化方法,稍微优化了一点点内存总比没有优化强呀,有什么更好的方法可以告诉我学习下嘿嘿

/#pragma mark - 内存优化
//在移除self.map的同时,重新加载mapView,两行代码就可以达到释放内存的效果
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
    
    [self.mapView removeFromSuperview];
    [self.view addSubview:mapView];
    [self applyMapViewMemoryHotFix];
    
    
}

- (void)dealloc {
    self.mapView.showsUserLocation = NO;
    self.mapView.userTrackingMode  = MKUserTrackingModeNone;
    [self.mapView.layer removeAllAnimations];
    [self.mapView removeAnnotations:self.mapView.annotations];
    [self.mapView removeOverlays:self.mapView.overlays];
    [self.mapView removeFromSuperview];
    self.mapView.delegate = nil;
    self.mapView = nil;
}
- (void)applyMapViewMemoryHotFix{
    
    switch (self.mapView.mapType) {
        case MKMapTypeHybrid:
        {
            self.mapView.mapType = MKMapTypeStandard;
        }
            
            break;
        case MKMapTypeStandard:
        {
            self.mapView.mapType = MKMapTypeHybrid;
        }
            
            break;
        default:
            break;
    }
    
    
    self.mapView.mapType = MKMapTypeStandard;
    
    
    
}

结束语

慢慢学习iOS共同进步吧,有什么问题和好的建议给我留个言,码字不易点个喜欢吧可以的话,附上Demo地址
写完又发现搜索按钮旁边的取消按钮为英文cancel,如果我们不写一行代码怎么让它变为中文取消呢,那就是在info.plistLocalization native development region这一项改为en,China,那么如果用户把手机语言设成英文, 那么显示的就是英文, 设置成中文,那么显示的就是中文.

你可能感兴趣的:(MKMapView的基本使用)