定位、地理编码、逆地理编码
2016-05-03 14:21
459 查看
先看效果
代码下载
代码下载请猛戳这里!再看代码
- (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; }
相关文章推荐
- CSS浮动和定位学习笔记
- C#实现txt定位指定行完整实例
- Flex中怎么给表格中的滚动条定位避免刷新回到原处
- 一个JavaScript操作元素定位元素的实例
- js中的如何定位固定层的位置
- JS弹出层单纯的绝对定位居中示例代码
- 讲解iOS开发中基本的定位功能实现
- iOS中定位当前位置坐标及转换为火星坐标的方法
- JavaScript网页定位详解
- 微信企业号开发之微信考勤百度地图定位
- js实现滚动条滚动到某个位置便自动定位某个tr
- 在Android里完美实现基站和WIFI定位
- android 定位的4种方式介绍
- 基于JavaScript实现根据手机定位获取当前具体位置(X省X市X县X街道X号)
- 基于Android实现百度地图定位过程详解
- Android百度地图实现搜索和定位及自定义图标绘制并点击时弹出泡泡
- Android百度地图自定义公交路线导航
- Android判断服务是否运行及定位问题实例分析
- Android百度地图定位后获取周边位置的实现代码
- IOS提醒用户重新授权打开定位功能