苹果原生地图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


目录
相关文章
|
11月前
|
数据采集 Java API
深度解析:爬虫技术获取淘宝商品详情并封装为API的全流程应用
本文探讨了如何利用爬虫技术获取淘宝商品详情并封装为API。首先介绍了爬虫的核心原理与工具,包括Python的Requests、BeautifulSoup和Scrapy等库。接着通过实战案例展示了如何分析淘宝商品页面结构、编写爬虫代码以及突破反爬虫策略。随后讲解了如何使用Flask框架将数据封装为API,并部署到服务器供外部访问。最后强调了在开发过程中需遵守法律与道德规范,确保数据使用的合法性和正当性。
|
7月前
|
缓存 数据可视化 定位技术
快递鸟快递API技术指南:获取物流轨迹信息与轨迹地图的解决方案
在当今电商竞争激烈的环境中,物流体验已成为提升用户满意度的关键因素。研究表明,超过 75% 的消费者会因物流信息不透明而放弃下单。
1591 1
|
9月前
|
人工智能 API 定位技术
MCP 开发实战:手把手教你封装高德地图与 arXiv API
本教程为 MCP(Model Context Protocol)开发实战第二阶段,带你从零封装第三方 API 为 AI 模型可用工具。通过高德地图地理编码与 arXiv 论文检索两个实例,涵盖项目搭建、工具声明、资源定义、错误处理等核心内容,助你快速上手 MCP 开发并集成至 Claude 使用。
|
缓存 测试技术 API
API的封装步骤流程
API封装流程是一个系统化的过程,旨在将内部功能转化为可复用的接口供外部调用。流程包括明确需求、设计接口、选择技术和工具、编写代码、测试、文档编写及部署维护。具体步骤为确定业务功能、数据来源;设计URL、请求方式、参数及响应格式;选择开发语言、框架和数据库技术;实现数据连接、业务逻辑、错误处理;进行功能、性能测试;编写详细文档;部署并持续维护。通过这些步骤,确保API稳定可靠,提高性能。
|
安全 API Swift
如何在苹果内购开发中获取App Store Connect API密钥-共享密钥理解内购安全-优雅草卓伊凡
如何在苹果内购开发中获取App Store Connect API密钥-共享密钥理解内购安全-优雅草卓伊凡
1086 15
如何在苹果内购开发中获取App Store Connect API密钥-共享密钥理解内购安全-优雅草卓伊凡
|
数据采集 搜索推荐 API
Python 原生爬虫教程:京东商品列表页面数据API
京东商品列表API是电商大数据分析的重要工具,支持开发者、商家和研究人员获取京东平台商品数据。通过关键词搜索、分类筛选、价格区间等条件,可返回多维度商品信息(如名称、价格、销量等),适用于市场调研与推荐系统开发。本文介绍其功能并提供Python请求示例。接口采用HTTP GET/POST方式,支持分页、排序等功能,满足多样化数据需求。
|
数据采集 API 数据格式
Python 原生爬虫教程:京东商品详情页面数据API
本文介绍京东商品详情API在电商领域的应用价值及功能。该API通过商品ID获取详细信息,如基本信息、价格、库存、描述和用户评价等,支持HTTP请求(GET/POST),返回JSON或XML格式数据。对于商家优化策略、开发者构建应用(如比价网站)以及消费者快速了解商品均有重要意义。研究此API有助于推动电商业务创新与发展。
ThinkPHP 通用的API格式封装
本文介绍了在ThinkPHP框架中如何统一封装API返回格式的方法,包括创建状态码枚举类、编写统一格式化函数以及在BaseController和Error控制器中重写`__call`方法来处理不存在的方法或控制器调用,以实现统一的错误处理和返回格式。
ThinkPHP 通用的API格式封装
|
JSON JavaScript API
(API接口系列)商品详情数据封装接口json数据格式分析
在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!
|
负载均衡 API 数据安全/隐私保护
Zookeeper的客户端-原生的API
Zookeeper的客户端-原生的API