iOS——定位与地图

平时在写项目的时候可能会遇到需要使用定位服务的地方,比如说获取位置和导航等。因此这里我会使用OC自带的库以及苹果系统的地图来获取定位以及显示在地图上。

开始前的设置

在获取定位前,需要在项目文件的info中添加两个关键字,用于向用户请求定位服务。在请求定位服务的弹窗中会显示我们添加的字段

复制代码
<key>Privacy - Location When In Use Usage Description
<value>使用程序的时候获取本机位置

<key>Privacy - Location Always Usage Description
<value>总是获取本机位置

运行效果:

获取当前位置的经纬度

  • 在写代码前需要添加对应的库以及设置相关的属性:
objectivec 复制代码
#import <UIKit/UIKit.h>
// 关于定位以及地图的库
#import <MapKit/MKMapView.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>

@interface ViewController : UIViewController<CLLocationManagerDelegate, MKMapViewDelegate>

//设置一个定位管理者的属性
@property (nonatomic, strong) CLLocationManager *locationManager;
//存储推算出当前的地理位置信息,这个属性用于获取当前位置信息推算出的信息,比如有了经纬度而推算出的省、市、区等
@property (nonatomic, strong) CLGeocoder *geoCoder;

//定义属性获取存储到的位置信息
@property (nonatomic, retain) CLLocation *myLocation;

//MKMapView是iOS中MapKit框架中的一个类,用于显示地图,并提供与地图相关的交互功能
@property (nonatomic, strong) MKMapView *mapView;

@end
  • 开始定位:
objectivec 复制代码
//开始定位
- (void)dingWei {
    self.locationManager = [[CLLocationManager alloc] init];
    //desiredAccuracy用于指定定位服务精度, kCLLocationAccuracyBest表示最高精度,这个设置的优势是提供了最准确的位置信息,但代价是更高的能耗。其他定位精度设置,例如 kCLLocationAccuracyNearestTenMeters 或 kCLLocationAccuracyHundredMeters,它们提供了较低的精度但更节能。
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    //distanceFilter 属性用于设置设备移动的距离,当设备移动超过这个距离时,会触发位置更新。distanceFilter 被设置为 10.0 米。这意味着只有当设备移动超过 10.0 米时,才会触发新的位置更新。
    self.locationManager.distanceFilter = 10.0f;
    //检查设备的系统版本是否可以进行定位
    if ([CLLocationManager locationServicesEnabled]) {
        self.locationManager.delegate = self;
        //如果是,则调用 requestWhenInUseAuthorization 方法请求用户在应用处于前台时获取位置信息的授权。
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self.locationManager requestWhenInUseAuthorization];
        });
        self.geoCoder = [[CLGeocoder alloc] init];
    } else {
        NSLog(@"ERROR");
    }
}

CLLocationManager其相关的属性:

desiredAccuracy位置的精度属性,取值有如下几种:
kCLLocationAccuracyBest :精确度最佳
kCLLocationAccuracynearestTenMeters :精确度10m以内
kCLLocationAccuracyHundredMeters :精确度100m以内
kCLLocationAccuracyKilometer :精确度1000m以内
kCLLocationAccuracyThree:精确度3000m以内

  • 在代理方法中获取需要的位置信息
objectivec 复制代码
//在代理方法中获取需要的位置信息
//下面的方法中,locations是一个数组类型,其最后一个元素就是我们的经纬度坐标,类型为CLLocation,如果想将它设置为属性,修饰符一定要是retain
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    NSLog(@"%lu", locations.count);
    self.myLocation = locations.lastObject;
    NSLog(@"经度: %f, 纬度: %f", self.myLocation.coordinate.longitude, self.myLocation.coordinate.latitude);
    
    // 获取到位置后再进行反地理编码
    [self reverseGeocodeLocation:self.myLocation];
}

- (void)reverseGeocodeLocation:(CLLocation *)location {
    [self.geoCoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        if (placemarks.count > 0) {
            CLPlacemark *placemark = [placemarks objectAtIndex:0];
            NSLog(@"%@", placemark.name);
            NSString *city = placemark.locality;
            if (!city) {
                city = placemark.administrativeArea;
            }
            NSLog(@"位置名:%@", placemark.name);
            NSLog(@"街道:%@", placemark.thoroughfare);
            NSLog(@"子街道:%@", placemark.subThoroughfare);
            NSLog(@"市:%@", placemark.locality);
            NSLog(@"区:%@", placemark.subLocality);
            NSLog(@"国家:%@", placemark.country);
            
            // 在这里调用显示地图的方法
            [self showLocationOnMapWithLatitude:location.coordinate.latitude longitude:location.coordinate.longitude];
        }
    }];
}
  • 改变定位权限
objectivec 复制代码
// 在此回调中处理定位权限的改变
- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager {
    CLAuthorizationStatus status = manager.authorizationStatus;
    
    dispatch_async(dispatch_get_main_queue(), ^{
        if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorizedAlways) {
            // 在这里执行需要权限的操作,例如启动定位服务
            //设置允许在应用在后台运行时继续获取位置更新
            self.locationManager.allowsBackgroundLocationUpdates = NO;
            
            //开始获取设备的当前位置信息
            [self.locationManager startUpdatingLocation];
            self.geoCoder = [[CLGeocoder alloc] init];
            [self jiSuanDistance];
            self.mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
            self.mapView.delegate = self;
            [self.view addSubview:self.mapView];
        } else {
            NSLog(@"ERROR");
        }
    });
}
  • 获取定位出错时调用如下方法:
objectivec 复制代码
//获取位置出错的时候调用下面的协议方法
- (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    if (error) {
        NSLog(@"ERROR");
    }
}

运行结果:

测算两个经纬度之间的距离

objectivec 复制代码
//测算两个经纬度坐标之间的距离
- (void) jiSuanDistance {
    CLLocation *before = [[CLLocation alloc] initWithLatitude:11.111 longitude:222.222];
    CLLocationDistance meters = [self.myLocation distanceFromLocation:before];
    NSLog(@"相距: %f米", meters);
}

运行结果:

将位置定位在地图上

这里使用的是苹果自带的地图

objectivec 复制代码
- (void)showLocationOnMapWithLatitude:(CLLocationDegrees)latitude longitude:(CLLocationDegrees)longitude {
    //创建坐标点
    CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
    //以指定的坐标为中心,设置地图显示范围。这里的参数 1000 表示地图的纬度和经度跨度都为 1000 米。
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(coordinate, 1000, 1000);
    //调整地图显示区域,region 是一个 MKCoordinateRegion 结构体,表示地图的中心点和跨度,这里 region 代表指定的坐标点为中心
    [self.mapView setRegion:region animated:YES];
    
    // 添加标注
    //MKPointAnnotation是 MapKit 框架中的一部分,用于表示地图上的点标注
    MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
    //将coordinate属性设置为当前经纬度坐标
    annotation.coordinate = coordinate;
    //为地图添加标记
    [self.mapView addAnnotation:annotation];
}

运行结果:

相关推荐
玫瑰花开一片一片9 小时前
Flutter IOS 真机 Widget 错误。Widget 安装后系统中没有
flutter·ios·widget·ios widget
烎就是我11 小时前
100行代码swift从零实现一个iOS日历
ios·swift
鸿蒙布道师1 天前
鸿蒙NEXT开发通知工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
鸿蒙布道师1 天前
鸿蒙NEXT开发网络相关工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
cauyyl1 天前
xcode 16 遇到contains bitcode
react native·xcode
余生大大1 天前
关于Safari浏览器在ios<16.3版本不支持正则表达式零宽断言的解决办法
ios·正则表达式·safari
A_ugust__1 天前
Vue3集成浏览器API实时语音识别
人工智能·语音识别·xcode
爱分享的程序员1 天前
前端跨端框架的开发以及IOS和安卓的开发流程和打包上架的详细流程
android·前端·ios
Macle_Chen1 天前
ios开发中xxx.debug.dylib not found
ios·bug·debug.dylib