地图和定位(三)

2020-03-07  本文已影响0人  weyan

一、地理编码和反地理编码

地理编码:把地址转为经纬度
反地理编码:把经纬度转为地址

#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#import <AddressBook/AddressBook.h>
@interface ViewController ()

// 地址详情TextView
@property (weak, nonatomic) IBOutlet UITextView *addressDetailTV;

// 纬度TextField
@property (weak, nonatomic) IBOutlet UITextField *latitudeTF;

// 经度度TextField
@property (weak, nonatomic) IBOutlet UITextField *longtitudeTF;

// 用作地理编码、反地理编码的工具类
@property (nonatomic, strong) CLGeocoder *geoC;

@end

@implementation ViewController

#pragma mark - 懒加载
-(CLGeocoder *)geoC
{
    if (!_geoC) {
        _geoC = [[CLGeocoder alloc] init];
    }
    return _geoC;
}

// 地理编码
- (IBAction)geoCoder {

    if ([self.addressDetailTV.text length] == 0) {
        return;
    }

    // 地理编码方案一:直接根据地址进行地理编码(返回结果可能有多个,因为一个地点有重名)
//    [self.geoC geocodeAddressString:self.addressDetailTV.text completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
//        // 包含区,街道等信息的地标对象
//        CLPlacemark *placemark = [placemarks firstObject];
//        // 城市名称
//        NSString *city = placemark.locality;
//        // 街道名称
//        NSString *street = placemark.thoroughfare;
//        // 全称
//        NSString *name = placemark.name;
//        NSLog(@"city:%@,street:%@,name:%@",city,street,name);
////        self.addressDetailTV.text = [NSString stringWithFormat:@"%@", name];
//        self.latitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.latitude];
//        self.longtitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.longitude];
//    }];


    // 地理编码方案二:根据地址和区域两个条件进行地理编码(更加精确)
//    [self.geoC geocodeAddressString:self.addressDetailTV.text inRegion:nil completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
//        // 包含区,街道等信息的地标对象
//        CLPlacemark *placemark = [placemarks firstObject];
////        self.addressDetailTV.text = placemark.description;
//        NSLog(@"placemark:%@",placemark.description);
//        self.latitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.latitude];
//        self.longtitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.longitude];
//    }];

    // 地理编码方案三:
    NSDictionary *addressDic = @{
                                 (__bridge NSString *)kABPersonAddressCityKey : @"北京",
                                 (__bridge NSString *)kABPersonAddressStreetKey : @"棠下街"
                                 };
    [self.geoC geocodeAddressDictionary:addressDic completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
        CLPlacemark *placemark = [placemarks firstObject];
//        self.addressDetailTV.text = placemark.description;
        NSLog(@"placemark:%@",placemark.description);
        self.latitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.latitude];
        self.longtitudeTF.text = [NSString stringWithFormat:@"%f", placemark.location.coordinate.longitude];
    }];

}

// 反地理编码
- (IBAction)decode {
    // 过滤空数据
    if ([self.latitudeTF.text length] == 0 || [self.longtitudeTF.text length] == 0) {
        return;
    }
    // 创建CLLocation对象
    CLLocation *location = [[CLLocation alloc] initWithLatitude:[self.latitudeTF.text doubleValue] longitude:[self.longtitudeTF.text doubleValue]];
    // 根据CLLocation对象进行反地理编码
    [self.geoC reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * __nullable placemarks, NSError * __nullable error) {
        // 包含区,街道等信息的地标对象
        CLPlacemark *placemark = [placemarks firstObject];
        // 城市名称
//        NSString *city = placemark.locality;
        // 街道名称
//        NSString *street = placemark.thoroughfare;
        // 全称
        NSString *name = placemark.name;
        self.addressDetailTV.text = [NSString stringWithFormat:@"%@", name];
    }];

}

@end

二、获取当前城市名称(定位+反地理编码)

import UIKit
import CoreLocation

class ViewController: UIViewController {
    
    lazy var locationM: CLLocationManager = {
        let locationM: CLLocationManager = CLLocationManager()
        locationM.delegate = self
        return locationM
    }()
    
    //地理编码
    lazy var geoCoder: CLGeocoder = {
        return CLGeocoder()
    }()
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        
        //请求授权
        locationM.requestAlwaysAuthorization()
        //1.定位
        if CLLocationManager.locationServicesEnabled() {
            locationM.startUpdatingLocation()
        }
        
    }

}

extension ViewController: CLLocationManagerDelegate {
    
    //更新位置信息时调用
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        guard let lastLocation = locations.last else {
            return
        }
        
        if lastLocation.horizontalAccuracy < 0 {
            return
        }
        //在这里获取到位置信息,进行反地理编码(广州市:23.125178,113.280637)
        geoCoder.reverseGeocodeLocation(lastLocation) {
            (placemark: [CLPlacemark]?, error: Error?) in
            if error == nil{
                let place = placemark?.last
                print(place?.locality ?? "")
                //停止获取位置信息
                self.locationM.stopUpdatingLocation()
            }
        }
    }
    
}

三、使用第三方框架进行定位

(INTULocationManager框架)
注意:

代码如下:

import UIKit

class ViewController: UIViewController {

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        
//        subscribeLocation()
//        requestLocation()
    }
}

func subscribeLocation() {
    let logMgr: INTULocationManager = INTULocationManager.sharedInstance()
    logMgr.subscribeToLocationUpdates(withDesiredAccuracy: .city) { (loc:CLLocation?, accuracy: INTULocationAccuracy, status: INTULocationStatus) in
        if status == INTULocationStatus.success{
            print("定位成功location:\(String(describing: loc))")
        }else{
            print("定位失败")
        }
    }
}

func requestLocation() {
    let logMgr: INTULocationManager = INTULocationManager.sharedInstance()
    //delayUntilAuthorized: 确定超时时间从什么时候开始计算
    //true: 代表从用户授权过后开始计算超时时间
    //false: 代表从执行这行代码开始计算
    let requestID: INTULocationRequestID = logMgr.requestLocation(withDesiredAccuracy: .city, timeout: 10.0, delayUntilAuthorized: true) { (loc:CLLocation?, accuracy: INTULocationAccuracy, status: INTULocationStatus) in
        if status == INTULocationStatus.success{
            print("定位成功location:\(String(describing: loc))")
        }else{
            print("定位失败\(String(describing: status.rawValue))")
        }
    }
    //强制完成
//    logMgr.forceCompleteLocationRequest(requestID)
    //取消定位请求
//    logMgr.cancelHeadingRequest(requestID)
}

上一篇 下一篇

猜你喜欢

热点阅读