你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS之地圖的使用和實時描繪運動軌跡

iOS之地圖的使用和實時描繪運動軌跡

編輯:IOS開發綜合

這裡將通過代碼詳細的講解iOS地圖的使用:

第一步:添加框架(雖然不知道什麼時候起不用再添加框架,Xcode會自動的幫我們添加,但我們還是添加一下)

\

 

第二步:配置pliset文件

\

 

第三步:直接上代碼塊,一定要仔細閱讀

 

#import "ViewController.h"
//導入定位和地圖的兩個框架
#import 
#import 

//簽訂定位和地圖的代理協議
@interface ViewController ()

//位置管理者
@property (nonatomic, strong) CLLocationManager *localManager;
//地圖
@property (nonatomic, strong) MKMapView *mapView;
//存放用戶位置的數組
@property (nonatomic, strong) NSMutableArray *locationMutableArray;

@end

@implementation ViewController
#pragma mark - 位置管理者懶加載
- (CLLocationManager *)localManager
{
    if (_localManager == nil)
    {
        _localManager = [[CLLocationManager alloc]init];
       
        //設置定位的精度
        [_localManager setDesiredAccuracy:kCLLocationAccuracyBest];
        
        //位置信息更新最小距離
        _localManager.distanceFilter = 10;
        
        //設置代理
        _localManager.delegate = self;
        
       //如果沒有授權則請求用戶授權,
       //因為 requestAlwaysAuthorization 是 iOS8 後提出的,需要添加一個是否能響應的條件判斷,防止崩潰
        if ([CLLocationManager authorizationStatus]==kCLAuthorizationStatusNotDetermined && [_localManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
            [_localManager requestAlwaysAuthorization];
        }
    
        //創建存放位置的數組
        _locationMutableArray = [[NSMutableArray alloc] init];
    }
    return _localManager;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    //全屏顯示地圖並設置地圖的代理
    _mapView = [[MKMapView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    _mapView.delegate = self;
    
    //是否啟用定位服務
    if ([CLLocationManager locationServicesEnabled]){
        NSLog(@"開始定位");
        //調用 startUpdatingLocation 方法後,會對應進入 didUpdateLocations 方法
        [self.localManager startUpdatingLocation];
    }
    else{
        
        NSLog(@"定位服務為關閉狀態,無法使用定位服務");
    }
    
    //用戶位置追蹤
    _mapView.userTrackingMode = MKUserTrackingModeFollow;
    /**
     地圖的樣式:
     MKMapTypeStandard, 標准地圖
     MKMapTypeSatellite, 衛星地圖
     MKMapTypeHybrid, 混合地圖
     MKMapTypeSatelliteFlyover, 衛星立體地圖
     MKMapTypeHybridFlyover, 混合立體地圖
     */
    _mapView.mapType = MKMapTypeStandard;
    
    [self.view addSubview:_mapView];
}

#pragma mark - MKMapViewDelegate
/**
更新用戶位置,只要用戶改變則調用此方法(包括第一次定位到用戶位置)
第一種畫軌跡的方法:我們使用在地圖上的變化來描繪軌跡,這種方式不用考慮從 CLLocationManager 取出的經緯度在 mapView 上顯示有偏差的問題
 */
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
    
    NSString *latitude = [NSString stringWithFormat:@"%3.5f",userLocation.coordinate.latitude];
    NSString *longitude = [NSString stringWithFormat:@"%3.5f",userLocation.coordinate.longitude];
    NSLog(@"更新的用戶位置:緯度:%@, 經度:%@",latitude,longitude);
    
    //設置地圖顯示范圍(如果不進行區域設置會自動顯示區域范圍並指定當前用戶位置為地圖中心點)
    MKCoordinateSpan span = MKCoordinateSpanMake(0.05, 0.05);
    MKCoordinateRegion region=MKCoordinateRegionMake(userLocation.location.coordinate, span);
    [_mapView setRegion:region animated:true];

    if (_locationMutableArray.count != 0) {

        //從位置數組中取出最新的位置數據
        NSString *locationStr = _locationMutableArray.lastObject;
        NSArray *temp = [locationStr componentsSeparatedByString:@","];
        NSString *latitudeStr = temp[0];
        NSString *longitudeStr = temp[1];
        CLLocationCoordinate2D startCoordinate = CLLocationCoordinate2DMake([latitudeStr doubleValue], [longitudeStr doubleValue]);
    
        //當前確定到的位置數據
        CLLocationCoordinate2D endCoordinate;
        endCoordinate.latitude = userLocation.coordinate.latitude;
        endCoordinate.longitude = userLocation.coordinate.longitude;
        
        //移動距離的計算
        double meters = [self calculateDistanceWithStart:startCoordinate end:endCoordinate];
        NSLog(@"移動的距離為%f米",meters);
        
        //為了美化移動的軌跡,移動的位置超過10米,方可添加進位置的數組
        if (meters >= 0){
            
            NSLog(@"添加進位置數組");
            NSString *locationString = [NSString stringWithFormat:@"%f,%f",userLocation.coordinate.latitude, userLocation.coordinate.longitude];
            [_locationMutableArray addObject:locationString];
            
            //開始繪制軌跡
            CLLocationCoordinate2D pointsToUse[2];
            pointsToUse[0] = startCoordinate;
            pointsToUse[1] = endCoordinate;
            //調用 addOverlay 方法後,會進入 rendererForOverlay 方法,完成軌跡的繪制
            MKPolyline *lineOne = [MKPolyline polylineWithCoordinates:pointsToUse count:2];
            [_mapView addOverlay:lineOne];
            
        }else{
        
            NSLog(@"不添加進位置數組");
        }
    }else{
    
        //存放位置的數組,如果數組包含的對象個數為0,那麼說明是第一次進入,將當前的位置添加到位置數組
        NSString *locationString = [NSString stringWithFormat:@"%f,%f",userLocation.coordinate.latitude, userLocation.coordinate.longitude];
        [_locationMutableArray addObject:locationString];
    }
}


-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id)overlay{
    
    if ([overlay isKindOfClass:[MKPolyline class]]){
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
        MKPolylineView *polyLineView = [[MKPolylineView alloc] initWithPolyline:overlay];
        polyLineView.lineWidth = 10; //折線寬度
        polyLineView.strokeColor = [UIColor blueColor]; //折線顏色
        return (MKOverlayRenderer *)polyLineView;
#pragma clang diagnostic pop
    }
    return nil;
}


#pragma mark - CLLocationManagerDelegate
/**
 *  當前定位授權狀態發生改變時調用
 *
 *  @param manager 位置管理者
 *  @param status  授權的狀態
 */
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
        case kCLAuthorizationStatusNotDetermined:{
            NSLog(@"用戶還未進行授權");
            break;
        }
        case kCLAuthorizationStatusDenied:{
            // 判斷當前設備是否支持定位和定位服務是否開啟
            if([CLLocationManager locationServicesEnabled]){
                
                NSLog(@"用戶不允許程序訪問位置信息或者手動關閉了位置信息的訪問,幫助跳轉到設置界面");
                
                NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                if ([[UIApplication sharedApplication] canOpenURL:url]) {
                    [[UIApplication sharedApplication] openURL: url];
                }
            }else{
                NSLog(@"定位服務關閉,彈出系統的提示框,點擊設置可以跳轉到定位服務界面進行定位服務的開啟");
            }
            break;
        }
        case kCLAuthorizationStatusRestricted:{
            NSLog(@"受限制的");
            break;
        }
        case kCLAuthorizationStatusAuthorizedAlways:{
            NSLog(@"授權允許在前台和後台均可使用定位服務");
            break;
        }
        case kCLAuthorizationStatusAuthorizedWhenInUse:{
            NSLog(@"授權允許在前台可使用定位服務");
            break;
        }
            
        default:
            break;
    }
}
/**
 我們並沒有把從 CLLocationManager 取出來的經緯度放到 mapView 上顯示
 原因:
 我們在此方法中取到的經緯度依據的標准是地球坐標,但是國內的地圖顯示按照的標准是火星坐標
 MKMapView 不用在做任何的處理,是因為 MKMapView 是已經經過處理的
 也就導致此方法中獲取的坐標在 mapView 上顯示是有偏差的
 解決的辦法有很多種,可以上網就行查詢,這裡就不再多做贅述
 */
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    // 設備的當前位置
    CLLocation *currLocation = [locations lastObject];
    
    NSString *latitude = [NSString stringWithFormat:@"緯度:%3.5f",currLocation.coordinate.latitude];
    NSString *longitude = [NSString stringWithFormat:@"經度:%3.5f",currLocation.coordinate.longitude];
    NSString *altitude = [NSString stringWithFormat:@"高度值:%3.5f",currLocation.altitude];
    
    NSLog(@"位置發生改變:緯度:%@,經度:%@,高度:%@",latitude,longitude,altitude);
    
    [manager stopUpdatingLocation];
}

//定位失敗的回調方法
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"無法獲取當前位置 error : %@",error.localizedDescription);
}


#pragma mark - 距離測算
- (double)calculateDistanceWithStart:(CLLocationCoordinate2D)start end:(CLLocationCoordinate2D)end {
    
    double meter = 0;
    
    double startLongitude = start.longitude;
    double startLatitude = start.latitude;
    double endLongitude = end.longitude;
    double endLatitude = end.latitude;
    
    double radLatitude1 = startLatitude * M_PI / 180.0;
    double radLatitude2 = endLatitude * M_PI / 180.0;
    double a = fabs(radLatitude1 - radLatitude2);
    double b = fabs(startLongitude * M_PI / 180.0 - endLongitude * M_PI / 180.0);
    
    double s = 2 * asin(sqrt(pow(sin(a/2),2) + cos(radLatitude1) * cos(radLatitude2) * pow(sin(b/2),2)));
    s = s * 6378137;
    
    meter = round(s * 10000) / 10000;
    return meter;
}


@end

代碼中詳細講解了地圖的使用以及真機情況下可能出現的各種情況,地圖的定位、位移是經常使用的功能,可以通過以上的代碼入門,更好的幫助你進行地圖功能的開發;代碼的實現還有實時繪制軌跡的功能,當然實時繪制軌跡的功能也不是盡如完美,而且現在百度還推出了鷹眼地圖,可以查看自己的軌跡信息。進行開發就是選擇最適合自己的方法完成功能需求。
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved