定位、地理编码、逆地理编码

先看效果

这里写图片描述

代码下载

代码下载请猛戳这里!

再看代码


- (CLLocationManager *)locationManager
{
    //是否允许定位
    /**
     *  [CLLocationManager locationServicesEnabled] 确定用户是否已启用位置服务。
     *  [CLLocationManager authorizationStatus] 返回调用应用程序的当前授权状态。
            kCLAuthorizationStatusDenied:用户已经明确地拒绝了该应用程序的授权,或者
     在设置中禁用位置服务。
            kCLAuthorizationStatusNotDetermined:用户尚未对该应用程序作出选择
     */
    NSLog(@"%i,%i",[CLLocationManager locationServicesEnabled],[CLLocationManager authorizationStatus]);
    if ((![CLLocationManager locationServicesEnabled]) || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
        [self showAlertViewControllerWithMessage:@"请到\"设置—隐私—定位服务\"开启本软件的定位服务"];
        return nil;
    }

    if (!_locationManager) {
        //创建定位管理者
        _locationManager = [[CLLocationManager alloc] init];
        //设置管理者代理
        _locationManager.delegate = self;
        //desiredAccuracy:所需的位置精度。位置服务将尽力实现
        _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        //distanceFilter:指定米的最小更新距离。distanceFilter的值越小,应用程序的耗电量就越大。
        _locationManager.distanceFilter = 1000.0f;
        //如果是iOS8以上系统
        if ([[UIDevice currentDevice].systemVersion floatValue] > 8.0) {
            //requestAlwaysAuthorization: 总是允许访问地理信息,需要在plist文件中设置NSLocationAlwaysUsageDescription
//            [_locationManager requestAlwaysAuthorization];
            //requestWhenInUseAuthorization: 在使用应用期间允许访问地理信息,需要在plist文件中设置NSLocationWhenInUseUsageDescription
            [_locationManager requestWhenInUseAuthorization];
        }
    }

    return _locationManager;
}

#pragma mark - 控制器周期
- (void)dealloc
{
    //移除通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)viewDidLoad {
    [super viewDidLoad];

    [self.locTextField becomeFirstResponder];

    //distanceFromLocation: 计算两个CLLocation对象的距离
    NSLog(@"衡阳到长沙:%f米",[[[CLLocation alloc] initWithLatitude:28.194 longitude:112.982] distanceFromLocation:[[CLLocation alloc] initWithLatitude:29.6 longitude:112.6]]);

    //监听键盘通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardChanged:) name:UIKeyboardWillChangeFrameNotification object:nil];
}
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [self.locationManager startUpdatingLocation];
}

#pragma mark - 触摸点击方法
- (IBAction)locationAction:(UIButton *)sender {
    /**
     *  如果是iOS9的系统,定位的代理方法还是不会执行的,因为iOS9引入了新特性App Transport Security (ATS)。
     解决方案:首先在Info.plist中添加NSAppTransportSecurity类型Dictionary。
     然后在NSAppTransportSecurity下添加NSAllowsArbitraryLoads类型Boolean,值设为YES
     */
    [self.locationManager startUpdatingLocation];
}
- (IBAction)geocodingAction:(UIButton *)sender {
    if (![self isBlinkStr:self.locTextField.text]) {
        [self geoCodingLocationStr:self.locTextField.text];
    }
}
- (IBAction)reGeocodingAction:(UIButton *)sender {
    [self.view endEditing:YES];

    if ((![self isBlinkStr:self.reLatitudeTextField.text] && (![self isBlinkStr:self.reLongitudeTextField.text]))) {
        [self reGeoCodingLatitude:[self.reLatitudeTextField.text doubleValue] andLongitude:[self.reLongitudeTextField.text doubleValue]];
    }
    else
    {
        [self showAlertViewControllerWithMessage:@"请输入经纬度!"];
    }
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}
/*
 UIKeyboardAnimationCurveUserInfoKey = 7;  // 动画的执行节奏(速度)
 UIKeyboardAnimationDurationUserInfoKey = "0.25"; // 键盘弹出\隐藏动画所需要的时间
 UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}";
 UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 588}";
 UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 372}";
 UIKeyboardFrameChangedByUserInteraction = 0;

 // 键盘弹出
 UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";// 键盘刚出来那一刻的frame
 UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 264}, {320, 216}}"; //  键盘显示完毕后的frame

 // 键盘隐藏
 UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 264}, {320, 216}}";
 UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 480}, {320, 216}}";
 */
- (void)keyBoardChanged:(NSNotification *)sender
{
    UIView *view = [self findFirstResponder:self.view];
    CGRect keyBF = [sender.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat distance = CGRectGetMaxY(view.frame) - keyBF.origin.y;

    //首尾式动画
    [UIView beginAnimations:nil context:nil];
    //设置动画时间
    [UIView setAnimationDuration:[sender.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    //设置动画节奏
    [UIView setAnimationCurve:[sender.userInfo[UIKeyboardAnimationDurationUserInfoKey] integerValue]];
    //设置动画
    if (distance > 0) {
        CGFloat spacing = 8;
        self.view.transform = CGAffineTransformMakeTranslation(0, -distance - spacing);
    }
    else
    {
        self.view.transform = CGAffineTransformIdentity;
    }
}

#pragma mark - 自定义方法
/**
 *  地理编码
 *
 *  @param str 地名
 */
- (void)geoCodingLocationStr:(NSString *)str
{
    //地理编码
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder geocodeAddressString:str completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        if (error) {
            [self showAlertViewControllerWithMessage:@"您的地址输入有误!"];
        }
        else
        {
            //注意取出最前面的地址(准确)
            //CLPlacemark:代表一个地理位置的地标数据。
            CLPlacemark *placeMark = [placemarks firstObject];
            self.latitudeTextField.text = [NSString stringWithFormat:@"%f",placeMark.location.coordinate.latitude];
            self.longitudeTextField.text = [NSString stringWithFormat:@"%f",placeMark.location.coordinate.longitude];
            self.detailLocTextField.text = placeMark.name;
        }
    }];
}
/**
 *  逆地理编码
 *
 *  @param latitude  纬度
 *  @param longitude 经度
 */
- (void)reGeoCodingLatitude:(CLLocationDegrees)latitude andLongitude:(CLLocationDegrees)longitude
{
    //取出CLLocation位置对象
    CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
    //逆地理编码
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        if (error) {
            [self showAlertViewControllerWithMessage:@"没有找到此经纬度的地理信息!"];
        }
        else
        {
            //注意取出最前面的地址(准确)
            //CLPlacemark:代表一个地理位置的地标数据。
            CLPlacemark *pMark = [placemarks firstObject];
            self.reDetailLocTextField.text = pMark.name;
        }
    }];
}
/**
 *  字符串判空
 */
- (BOOL)isBlinkStr:(NSString *)str
{
    /**
     *  stringByTrimmingCharactersInSet函数过滤字符串中的特殊符号
     */
    if (str == nil || str == NULL) {
        return YES;
    }
    else if ([str isKindOfClass:[NSNull class]])
    {
        return YES;
    }
    else if ([[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0)//去掉两端的空白字符
    {
        return YES;
    }

    return NO;
}
/**
 *  显示提示框
 *
 *  @param message 提示的信息
 */
- (void)showAlertViewControllerWithMessage:(NSString *)message
{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
    [alertController addAction:okAction];
    [self presentViewController:alertController animated:YES completion:nil];
}
/**
 *  查找第一响应者
 *
 *  @param view 从哪个视图上查找
 *
 *  @return 第一响应者View
 */
- (UIView *)findFirstResponder:(UIView *)view
{
    if ([view isFirstResponder]) {
        return view;
    }
    for (UIView *theView in view.subviews) {
        UIView *firstView = [self findFirstResponder:theView];
        if (firstView) {
            return firstView;
        }
    }

    return nil;
}

#pragma mark - <CLLocationManagerDelegate>代理方法
/**
 *  只要定位到用户信息就会调用此方法(调用的平率非常高)
 *
 *  @param manager   定位管理者
 *  @param locations  装着CLLocation对象
 */
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
    //此处locations存储了持续更新的位置坐标值,取最后一个值为最新位置,如果不想让其持续更新位置,则在此方法中获取到一个值之后让locationManager stopUpdatingLocation
    CLLocation *location = [locations lastObject];
    //逆地理编码
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
        if (error) {
            NSLog(@"此地址错误");
        }
        else
        {
            //取出最前面的地址(准确)
            CLPlacemark *pMark = [placemarks firstObject];
            self.currentLocTextField.text = pMark.name;
            NSLog(@"%f,%f,%@,%@,%@",location.coordinate.latitude,location.coordinate.longitude,pMark.name,pMark.locality,pMark.addressDictionary[@"City"]);
        }
    }];
    //停止定位(省电措施:只要不想用定位服务,就马上停止定位服务)
    [manager stopUpdatingLocation];
}

#pragma mark - <UITextFieldDelegate>代理方法
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    if (textField == self.locTextField && (![self isBlinkStr:self.locTextField.text])) {
        [self geoCodingLocationStr:self.locTextField.text];
    }
    else if ((textField == self.reLatitudeTextField || textField == self.reLongitudeTextField) && (![self isBlinkStr:self.latitudeTextField.text]) && (![self isBlinkStr:self.longitudeTextField.text]))
    {
        [self reGeoCodingLatitude:[self.reLatitudeTextField.text doubleValue] andLongitude:[self.reLongitudeTextField.text doubleValue]];
    }
    [textField resignFirstResponder];

    return YES;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 高德地图地理编码可以使用 AMap JavaScript API 实现。以下是一个简单的示例: 首先需要在 `index.html` 中引入高德地图 JavaScript API: ```html <script src="https://webapi.amap.com/maps?v=1.4.15&key=your-amap-key"></script> ``` 然后在 Vue 组件中,可以使用以下代码获取当前位置的地理编码信息: ```vue <template> <div> <div ref="map" style="width: 100%; height: 400px;"></div> <div>{{ address }}</div> </div> </template> <script> export default { data() { return { address: "" }; }, mounted() { // 创建地图 const map = new AMap.Map(this.$refs.map, { zoom: 16 }); // 获取当前位置 map.plugin("AMap.Geolocation", () => { const geolocation = new AMap.Geolocation({ enableHighAccuracy: true, // 是否使用高精度定位,默认为 false timeout: 10000, // 超过 10 秒后停止定位,默认值为 无穷大 maximumAge: 0, // 定位结果缓存时间,默认值为 0 convert: true, // 自动偏移坐标,偏移后的坐标为高德坐标,默认为 true showButton: true, // 显示定位按钮,默认为 true buttonPosition: "LB", // 定位按钮的位置,默认为 'LB',左下角 buttonOffset: new AMap.Pixel(10, 10), // 定位按钮距离容器左下角的偏移量,默认为 Pixel(10, 20) showMarker: true, // 定位成功后在定位到的位置显示点标记,默认为 true showCircle: true, // 定位成功后用圆圈表示定位精度范围,默认为 true panToLocation: true, // 定位成功后将定位到的位置作为地图中心点,默认为 true zoomToAccuracy: true // 定位成功后自动调整地图缩放级别以适合定位结果的范围,默认为 true }); geolocation.getCurrentPosition((status, result) => { if (status === "complete") { this.getAddress(result.address); } else { console.log("获取当前位置信息失败"); } }); }); }, methods: { // 地理编码 getAddress(address) { this.address = address; } } }; </script> ``` 在 `mounted` 钩子函数中,我们使用 `AMap.Geolocation` 插件获取当前位置信息。然后在 `getCurrentPosition` 回调函数中,我们通过 `result.address` 获取当前位置的地理编码信息,并将其赋值给 `this.address`,以在页面中显示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值