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<CLPlacemark *> * _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<CLPlacemark *> * _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,那么如果用戶把手機語言設成英文, 那么顯示的就是英文, 設置成中文,那么顯示的就是中文.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容