苹果原生地图API封装

//
//  HYBLocationManager.h
//  MMLocationManager
//
//  Created by sixiaobo on 14-7-17.
//  Copyright (c) 2014年 Chen Yaoqiang. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "HYBSuperBaseViewController.h"

/*!
 * @brief 地图相关功能封装类,提供获取地理坐标功能、获取地理坐标和地址功能、获取地址功能、
 *        获取城市功能
 */
@interface HYBLocationManager : NSObject <MKMapViewDelegate>

// 定位时会加载到此mapView上,但Frame是CGRectZero,所以如果要显示此视图,需要在外部手动修改
@property (nonatomic, strong) MKMapView              *mapView;

// 最近一次保存下来的用户的地理位置(经纬度)
@property (nonatomic, assign) CLLocationCoordinate2D latestCoordinate;

// 最近一次保存下来的cityid,格式为@"1,1,0",分别是省ID,市ID,区ID,其中区ID如果没有,则可设置为0
@property (nonatomic, copy)   NSString               *latestCityID;

// 最近一次保存下来的库存地址,如北京省|北京市|朝阳区(非定位得到)
// 最近一次在保存下来的地址信息,这个是通过定位得到的信息,(下面的是定位得到)
// 如,
// 1、直辖市:@"北京市|北京市",
// 2、自治区的:@"广西壮族自治区|南宁市",
// 3、正常省份:@"广东省|中山市"
@property (nonatomic, copy)   NSString               *latestStockAddress;
@property (nonatomic, assign) BOOL                   isUsingLocation; // 是否是通过定位的

// 是否是用户选择了取消台允许用户访问用户位置
@property (nonatomic, assign) BOOL                   isDeniedToAccessLocation;
// 转圈圈显示需要的时候,就需要传这个参数
@property (nonatomic, weak)   HYBSuperBaseViewController *showNetworkStateInController;

// 单例方法
+ (HYBLocationManager *)sharedLocation;

/*!
 *  @brief 获取地理坐标
 *  @param locationCoordinateBlock 获取到的地理坐标信息会在这个block中返回
 */
// lc2d 即是定位到的地理坐标
typedef void (^HYBLocateCoordinateBlock)(CLLocationCoordinate2D lc2d);
- (void)locateCoordinate:(HYBLocateCoordinateBlock)locateCoordinateBlock;

/*!
 *  @brief 获取坐标和地址
 *  @param coordinateBlock 获取到的地理坐标信息会在这个block中返回
 *  @param addressBlock    获取到的地址信息
 */
// lc2d 即是定位到的地理坐标
typedef void (^HYBAddressBlock)(NSString *address);
- (void)locateCoordinate:(HYBLocateCoordinateBlock)coordinateBlock
                   address:(HYBAddressBlock)addressBlock;

/*!
 *  @brief 获取地址
 *  @param addressBlock 获取到的地址信息
 */
typedef void (^HYBLocationErrorBlock) (NSError *error);
- (void)locateAddress:(HYBAddressBlock)addressBlock error:(HYBLocationErrorBlock)errorBlock;

@end
//
//  HYBLocationManager.m
//  MMLocationManager
//
//  Created by sixiaobo on 14-7-17.
//  Copyright (c) 2014年 Chen Yaoqiang. All rights reserved.
//

#import "HYBLocationManager.h"

#define  kLatestLongitude        @"kLatestLongitudeKey"  // 最新一次保存的纬度
#define  kLatestLatitude         @"kLatestLatitudeKey"   // 最新一次保存的经度
#define  kLatestStockAddress     @"kLatestStockAddress"  // 最新一次保存的库存地址
#define  kLatestCityID           @"kLatestCityID"        // 最新一次保存的地址

@interface HYBLocationManager ()

@property (nonatomic, copy) HYBLocateCoordinateBlock locateCoordinateBlock;
@property (nonatomic, copy) HYBAddressBlock          addressBlock;
@property (nonatomic, copy) HYBLocationErrorBlock    errorBlock;

@end

@implementation HYBLocationManager

+ (HYBLocationManager *)sharedLocation {
    static HYBLocationManager *sharedManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!sharedManager) {
            sharedManager = [[[self class] alloc] init];
        }
    });
    return sharedManager;
}

- (id)init {
    if (self = [super init]) {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        self.latestStockAddress = [defaults objectForKey:kLatestStockAddress];
        self.latestCityID = [defaults objectForKey:kLatestCityID];

        if (self.latestStockAddress == nil || self.latestCityID) {
            self.latestStockAddress = @"北京市|朝阳区";
            self.latestCityID = @"1,1,0";  // 北京省|北京市|朝阳区
            [defaults setObject:self.latestStockAddress forKey:kLatestStockAddress];
            [defaults setObject:self.latestCityID forKey:kLatestCityID];
            [defaults synchronize];
        }

        float longtitude = [defaults floatForKey:kLatestLongitude];
        float latitude = [defaults floatForKey:kLatestLatitude];
        self.latestCoordinate = CLLocationCoordinate2DMake(latitude, longtitude);
        self.isDeniedToAccessLocation = NO;
    }
    return self;
}

/*!
 *  @brief 获取地理坐标
 *  @param locationCoordinateBlock 获取到的地理坐标信息会在这个block中返回
 */
- (void)locateCoordinate:(HYBLocateCoordinateBlock)locateCoordinateBlock {
    self.locateCoordinateBlock = [locateCoordinateBlock copy];
    [self startLocating];
    return;
}

/*!
 *  @brief 获取坐标和地址
 *  @param coordinateBlock 获取到的地理坐标信息会在这个block中返回
 *  @param addressBlock    获取到的地址信息
 */
- (void)locateCoordinate:(HYBLocateCoordinateBlock)coordinateBlock
                 address:(HYBAddressBlock)addressBlock {
    self.locateCoordinateBlock = [coordinateBlock copy];
    self.addressBlock = [addressBlock copy];

    [self startLocating];
    return;
}

/*!
 *  @brief 获取地址
 *  @param addressBlock 获取到的地址信息
 */
- (void)locateAddress:(HYBAddressBlock)addressBlock error:(HYBLocationErrorBlock)errorBlock {
    self.addressBlock = [addressBlock copy];
    self.errorBlock = [errorBlock copy];
    [self startLocating];
    return;
}

#pragma mark - Private
// 启动定位
- (void)startLocating {
    if (self.mapView) { // 每次定位时先销毁之前的
        self.mapView.delegate = nil;
        self.mapView = nil;
    }
    self.mapView = [[MKMapView alloc] init];
    self.mapView.delegate = self;
    self.mapView.showsUserLocation = YES; // 打开定位功能

    return;
}

// 停止定位
- (void)stopLocation {
    _mapView.showsUserLocation = NO;
    _mapView.delegate = nil;
    _mapView = nil;
    return;
}

- (void)setLatestCityID:(NSString *)lastestCityID {
    if (_latestCityID != lastestCityID) {
        _latestCityID = nil;
        _latestCityID = [lastestCityID copy];
    }
    [kUserDefaults setObject:_latestCityID forKey:kLatestCityID];
    [kUserDefaults synchronize];
    return;
}

- (void)setLatestStockAddress:(NSString *)latestStockAddress {
    if (_latestStockAddress != latestStockAddress) {
        _latestStockAddress = nil;
        _latestStockAddress = [latestStockAddress copy];
    }
    [kUserDefaults setObject:latestStockAddress forKey:kLatestStockAddress];
    [kUserDefaults synchronize];
    return;
}

#pragma mark - MKMapViewDelegate
- (void)mapViewWillStartLocatingUser:(MKMapView *)mapView {
    NSLog(@"开始定位");
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
    if ([self.showNetworkStateInController respondsToSelector:@selector(startNetworkAnimating)]) {
        [self.showNetworkStateInController startNetworkAnimating];
    }
    return;
}

- (void)mapViewDidStopLocatingUser:(MKMapView *)mapView {
    NSLog(@"停止定位");
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    if ([self.showNetworkStateInController respondsToSelector:@selector(stopNetworkAnimating)]) {
        [self.showNetworkStateInController stopNetworkAnimating];
    }
    return;
}

// 定位失败处理
- (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error {
    [self stopLocation];
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];

    if (error.code == kCLErrorDenied) {
        self.isDeniedToAccessLocation = YES;
    }
    if (self.errorBlock) {
        self.errorBlock(error);
    }
    if ([self.showNetworkStateInController respondsToSelector:@selector(stopNetworkAnimating)]) {
        [self.showNetworkStateInController stopNetworkAnimating];
    }
    return;
}

// 定位成功处理
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
    CLLocation *newLocation = userLocation.location;
    self.latestCoordinate = mapView.userLocation.location.coordinate;
    NSUserDefaults *standard = [NSUserDefaults standardUserDefaults];

    // 保存地理坐标
    [standard setObject:@(self.latestCoordinate.longitude) forKey:kLatestLongitude];
    [standard setObject:@(self.latestCoordinate.latitude) forKey:kLatestLatitude];
    [[NSUserDefaults standardUserDefaults] synchronize];

    // 地理编码器
    CLGeocoder *geoCoder = [[CLGeocoder alloc] init];
    // 地理位置反编码
    [geoCoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
        for (CLPlacemark * placeMark in placemarks) {
            NSDictionary *addressDic = placeMark.addressDictionary;
            for (NSString *value in addressDic.allValues) {
                NSLog(@"value: %@", value);
            }
            NSString *state       = [addressDic objectForKey:@"State"];       // 省份名称
            NSString *city        = [addressDic objectForKey:@"City"];        // 城市名称
            NSString *district = [addressDic objectForKey:@"SubLocality"];    // 区
            self.latestStockAddress = [NSString stringWithFormat:@"%@|%@|%@",
                                       state, city ? city : state, district];
            [standard setObject:self.latestStockAddress forKey:kLatestStockAddress];
            [[NSUserDefaults standardUserDefaults] synchronize];
        }
        [self stopLocation];

        if (self.locateCoordinateBlock) {
            self.locateCoordinateBlock(self.latestCoordinate);
            self.locateCoordinateBlock = nil;
        }

        if (self.addressBlock) {
            self.addressBlock(self.latestStockAddress);
            self.addressBlock = nil;
        }
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
        if ([self.showNetworkStateInController respondsToSelector:@selector(stopNetworkAnimating)]) {
            [self.showNetworkStateInController stopNetworkAnimating];
        }
    }];
    return;
}

@end
时间: 2024-12-02 08:19:23

苹果原生地图API封装的相关文章

吐槽贴:百度地图 api 封装 的实用功能 [源码下载]

ZMap 类 功能介绍 ZMap 是学习百度地图 api 接口,开发基本功能后整的一个脚本类,本类方法功能大多使用 prototype 原型 实现: 包含的功能有:轨迹回放,圈画区域可编辑,判断几个坐标是否在一个圆圈内,生活服务查询,从经纬度获取地址信息,地图工具包括测距,获取面积,以积打印地图,地图全屏,实时路况,坐标是否在polygon区域内,打车方案,经过中间途经点,添加地图控件: 地图界面: ZMap.js 部分代码说明 /** * 百度地图 api 功能整合 * @author Glo

【高德地图API】从零开始学高德JS API(五)路线规划——驾车|公交|步行

原文:[高德地图API]从零开始学高德JS API(五)路线规划--驾车|公交|步行 先来看两个问题:路线规划与导航有什么区别?步行导航与驾车导航有什么区别? 回答: 1.路线规划,指的是为用户提供3条路线推荐.[高德]在提供路线规划的时候,会提供用户自定义路线规划功能,这是别家没有做到的.导航,指的是为驾车用户提示路口信息,向左向右,进入匝道等信息. 2.我们这里说的步行导航和驾车导航,严格的说,应该是路线规划.从A地到B地,如果是驾车,路线规划会将公路路网做为搜索数据:如果是步行,过街天桥.

iOS原生地图开发指南

iOS原生地图开发详解 在上一篇博客中:http://my.oschina.net/u/2340880/blog/414760.对iOS中的定位服务进行了详细的介绍与参数说明,在开发中,地位服务往往与地图框架结合使用,这篇博客主要对iOS官方的地图框架MapKit.framework进行介绍. 一.初始化地图视图与相关属性方法介绍 1.初始化地图视图 地图视图的展示依赖于MKMapView这个类,这个类继承于UIView,因此和其他View的使用方法类似.在我们需要展现地图的地方: ? 1 2

【百度地图API】如何批量转换为百度经纬度

原文:[百度地图API]如何批量转换为百度经纬度 摘要:      百度地图API的官网上提供了常用坐标转换的示例.但是,一次只能转换一个,真的非常麻烦!!这里结合了官方的示例,自制一个批量转换工具,供大家参考. ------------------------------------------------------------------------------------------ 因为我没有GPS坐标,就拿谷歌坐标做个示例了. 首先要注意的是,百度和谷歌的经纬度坐标顺序是相反的. 比

【高德地图API】从零开始学高德JS API(七)——定位方式大揭秘

原文:[高德地图API]从零开始学高德JS API(七)--定位方式大揭秘 摘要:关于定位,分为GPS定位和网络定位2种.GPS定位,精度较高,可达到10米,但室内不可用,且超级费电.网络定位,分为wifi定位和基站定位,都是通过获取wifi或者基站信息,然后查询对应的wifi或者基站位置数据库,得到的定位地点.定位数据库可以不断完善不断补充,所以,越定位越准确.本文详细描述了,如果使用高德JS API来实现位置定位.城市定位的方法,包含了IP定位,浏览器定位,检索定位等多种网络定位方法.当然,

php版微信JS-SDK地理位置与腾讯地图API实例

根据前面几个地理位置教程,最终把腾讯地图的Web Service API 写完善的类,call不同接口时,注意不同的参数,因为每个差数都稍有不同,是直接影响到显示结果,所以详细请查看官方的文档 Web Service API文档 继续以TP为框架给代码和实例效果! QQMapModel类: <?php namespace Home\Model; class QQMapModel {     const         SEARCH_API = 'http://apis.map.qq.com/ws

【高德地图API】从零开始学高德JS API(二)地图控件与插件——测距、圆形编辑器、鼠标工具、地图类型切换、鹰眼鱼骨

原文:[高德地图API]从零开始学高德JS API(二)地图控件与插件--测距.圆形编辑器.鼠标工具.地图类型切换.鹰眼鱼骨 摘要:无论是控件还是插件,都是在一级API接口的基础上,进行二次开发,封装的一系列更加便于开发者使用,减少开发者工作量的二级API接口.除了官方通用的鱼骨.鹰眼控件,还有大量官方开发的地图插件,类似谷歌的lib.当然本文还会介绍自定义插件的使用.   -------------------------------------------------------------

【高德地图API】那些年我们一起开发的APP—即LBS应用模式分享

原文:[高德地图API]那些年我们一起开发的APP-即LBS应用模式分享  摘要:利用地图API都能做些什么应用呢?应用商店里所有的分类,都可以结合上LBS来丰富应用.除了传统的生活服务应用,还有新潮的AR实景,可穿戴设备,甚至炫酷的游戏.那么,LBS已经做了哪些事情呢?本文详细介绍了LBS应用模式.一起来细数吧,那些年我们一起开发的APP. (在文章结尾处,有2014LBS应用大赛的信息, 不仅可以写代码拿大奖,提交创意也有奖品呢.快去参加吧.)   一.导航类 苹果地图和谷歌地图,在中国的地

亚马逊发布测试版地图API 欲挑战谷歌地图地位

中介交易 SEO诊断 淘宝客 云主机 技术大厅 在此之前,苹果也在iOS 6移动平台中用自己的地图服务取代了谷歌地图.(TechWeb配图) 新浪科技讯 北京时间9月17日晚间消息,亚马逊今日面向开发人员推出了新的测试版地图API(应用编程接口),以便Kindle Fire应用开发人员使用自家的地图技术来取代谷歌地图. 亚马逊在官方博客中称:"在我们发布Kindle Fire HD的同时,我们还向开发者社区提供了亚马逊地图API.该API允许开发人员在 Kindle Fire和Kindle Fi