iOS开发-------地图定位显示周围微博(CLLocationManager 定位管理)

       上一篇说到如何给一个固定的位置在地图上显示,但是手机端的定位肯定不是这样的,而是需要随着我们的位置变化而定位,所以就需要到了这一篇中的一个类CLLocationManager(定位管理器),看到manager的第一感觉,会不会是个单例,但这一个类不是一个单例,但起着和单例一样作用,因为它所指向的内存就是手机内部负责定位的组件,而这个硬件组件的地址是唯一的,所以alloc init之后,所得到的地址是一样的。话不多讲,代码以及视图才是王道。


源码的GitHub:https://github.com/YRunIntoLove/LocationPractise


      相比于上一篇文章中的weiboManager中请求数据的方法,昨天进行了相应的优化,优化只不过是对参数的要求更加简洁,毕竟逻辑层越简单越好,数据层的处理麻烦点不是问题,model类没有发生变化,方法修改如下:

/**
 *  获取某个位置的周边微博
 *
 *  @param access_token 用的token值
 *  @param myLocation   当前的位置
 *  @param count        获取数量
 *  @param b            获取的微博列表
 */
-(void)getWeiboNearByTimeLineWithToken:(NSString *)access_token WithLocation:(CLLocationCoordinate2D)myLocation Count:(NSInteger)count BlockHandle:(WBM)b
{
    //创建参数字典
    NSDictionary * parameterDict = @{@"access_token":access_token,@"lat":[NSString stringWithFormat:@"%lf",myLocation.latitude],@"long":[NSString stringWithFormat:@"%lf",myLocation.longitude],@"count":[NSString stringWithFormat:@"%ld",count]};
    
    //开始请求
    [self.operationManager GET:nearby_timeLine parameters:parameterDict success:^void(AFHTTPRequestOperation * operation, NSData * data) {
        
        NSError * error;
        
        //创建一个字典接收数据
        NSDictionary * resultDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
        
        //接收数组
        NSArray * weiboArray = resultDict[@"statuses"];
        
        //创建一个可变数组,存储最后的结果
        NSMutableArray * resultArray = [NSMutableArray array];
        
        //开始遍历,并且添加数据
        for (NSDictionary * tempDict in weiboArray)
        {
            
            //创建一个微博模型
            Weibo * weibo = [[Weibo alloc]init];
            
            //开始赋值
            weibo.userName = tempDict[@"user"][@"name"];
            weibo.weiboText = tempDict[@"text"];
            
            //为坐标赋值
            NSString * lat = tempDict[@"geo"][@"coordinates"][0];
            NSString * longc = tempDict[@"geo"][@"coordinates"][1];
            CLLocationCoordinate2D temp = CLLocationCoordinate2DMake([lat doubleValue], [longc doubleValue]);
            weibo.weiboLocationCoordinate2D = temp;
            
            //NSLog(@"位置是:%g,%g",weibo.weiboLocationCoordinate2D.latitude,weibo.weiboLocationCoordinate2D.longitude);
            
            //添加到可变数组
            [resultArray addObject:weibo];
        }
        
        //回调
        b([NSArray arrayWithArray:resultArray]);
        
    } failure:^void(AFHTTPRequestOperation * operation, NSError * error) {
        ;
    }];
}



    CLLocationManager组件,在iOS8之前的用法就不再提及,因为在iOS8上突然发生了几个重大变动,所以就按照iOS8之后的方法以及属性进行说明

在用这个组件之前,必须先引入一个头文件

#import <CoreLocation/CoreLocation.h>


然后需要履行一个协议,如下

@interface ViewController ()<MKMapViewDelegate,CLLocationManagerDelegate>


随后需要在延展中添加这个属性,其实添加不添加无所谓,毕竟是单例作用,但是加上感觉用起来会好许多

//定位管理器
@property(nonatomic,strong)CLLocationManager * locationManager;

然后viewDidLoad中也没有了那么多定位的语句,看起来会简洁了许多,

- (void)viewDidLoad {
    [super viewDidLoad];

    //初始化地图视图
    self.mapView = [[MKMapView alloc]initWithFrame:self.view.frame];
    
    //初始化单例
    self.weiboManager = [WeiBoManager shareWeiBoManager];
    
    //初始化位置管理
    self.locationManager = [[CLLocationManager alloc]init];
    
    //设置导航栏的信息
    self.navigationItem.title = @"地图";
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(freshMapWithCheck)];//添加一个刷新按钮
    
    //设置代理,不要忘记设置代理
    self.mapView.delegate = self;
    self.locationManager.delegate = self;
 
    //判断当前定位的状态
    [self freshMapWithCheck];
    
    //添加视图
    [self.view addSubview:self.mapView];

}

freshMapWithCheck的作用是什么呢,因为在iOS8之后,需要用户授权才能够获取数据,也表现了良好的保密性,所以定位之前是需要判断一下定位状态的,如下

/**
 *  刷新按钮的回调 以及用于判断当前状态是否能够请求位置
 */
-(void)freshMapWithCheck
{
    //如果定位管理器获得了用户的允许
    if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse)
    {
        //开始请求位置
        [self.locationManager startUpdatingLocation];
    }
    
    else
    {
        //开始请求授权
        [self.locationManager requestWhenInUseAuthorization];
    }

}

接着实现协议的三个方法,因为三个方法足以,所以其他的方法可以通过观看开发文档更细致的了解


1、每次获取地理数据的时候,都要先判断一下用户是否允许,只有允许了,才可以获取数据,所以回调方法名字叫做didChangeAuthorizationStatus的方法,即授权状态发生变化时,如下

/**
 *  定位管理器  授权状态发生变化时
 *
 *  @param manager 定位管理器
 *  @param status  当前授权的状态
 */
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {//判断当前状态
        case kCLAuthorizationStatusAuthorizedWhenInUse://在用时已经授权
            //请求位置
            [self.locationManager startUpdatingLocation];
            break;
        case kCLAuthorizationStatusNotDetermined://授权待定
            //请求授权
            [self.locationManager requestWhenInUseAuthorization];
            break;
        default:
            break;
    }
}

2、如果定义失败,那么需要一个失败时的回调,叫做DidFailWithError的方法,顾名思义,是请求失败或者发生错误时的回调,因为不是真机调试,所以用控制台打印一下

/**
 *  定位失败时候的回调方法
 *
 *  @param manager 定位管理器
 *  @param error   错误信息
 */
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"定位失败!");
}

3、就是比较重要的一步,即请求位置成功后的操作。请求之后首先需要获取当前位置,然后将地图锁定到当前位置上,接着请求附近的微博,显示,方法名字叫做:didUpdateLocation,方法如下

#pragma mark - CLLocationManager Delegate
/**
 *  位置更新完毕之后进行的回调
 *
 *  @param manager   定位管理者
 *  @param locations 存储位置的数组,最后一个为最新的定位
 */
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    //获取最新定位
    CLLocation * location = locations.lastObject;
    
    NSLog(@"获取了最新定位!");
    
    //停止请求位置
    [self.locationManager stopUpdatingLocation];
    
    //初步定义地图显示的位置
    MKCoordinateRegion lastRegion;
    lastRegion.center = location.coordinate;
    lastRegion.span = MKCoordinateSpanMake(0.1, 0.1);
    //更新地图范围
    self.mapView.region = lastRegion;
    
    //开始请求微博
    [self.weiboManager getWeiboNearByTimeLineWithToken:token WithLocation:lastRegion.center Count:3 BlockHandle:^(NSArray *array) {
       
        //将请求的微博添加到地图上
        [self.mapView addAnnotations:array];
    }];
}

这样是不是就成功了呢,试一下呗,如果不进行相应的处理,一般情况如下




为什么出现这种情况呢,是因为开发文档有这么一句话

/*
 *  purpose
 *  
 *  Discussion:
 *      Allows the application to specify what location will be used for in their app. This
 *      will be displayed along with the standard Location permissions dialogs. This property will need to be
 *      set prior to calling startUpdatingLocation.
 *
 *      Deprecated.  Set the purpose string in Info.plist using key NSLocationUsageDescription.
 *<span style="white-space:pre">	</span>废弃,将理由字符串设置在 info.plist中 用键值 NSLocationUsageDescription,所以以前是直接用这个属性来赋值的,在iOS6就已经被废除了
 */
@property(copy, nonatomic) NSString *purpose __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_NA, __IPHONE_3_2, __IPHONE_6_0);



就是说在ios8之后,要想得到用户的授权必须要在supportise File中的info.plist,也就是配置文件中加这么一个字段,说明请求位置的原因,尽量简洁即可,如何添加?



左边的箭头不要点开,直接点+号,添加的key名字是NSLocationWhenInUseUsageDescription,后面的值就是填理由,比如我的是RunIntoLove请求定位



然后运行一下,就会出现图文框了



点击allow即表示允许,楼主点击了allow


点击允许之后,却发现控制台出现以下打印


0.0请不要说楼主是骗子,因为用的是模拟器,没有实际的定位硬件,但是可以模拟位置,有两种方法


1、第一种方法


点击custom Location,接着输入经纬度,楼主输入的是天安门的经纬度



点击回车,就有效果了,来看看


2、第二种方法




点击那个类似导航的箭头,比如楼主选择的是中国香港




来看下效果如何,不要忘记点击刷新啊,这次可不是自动刷新了



来到香港了,至于为什么会有导航栏,因为没有用stroyboard拖拽,所以必然在appDelegate中用代码实现了如下,

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    //创建窗口
    UIWindow * window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    self.window = window;
    
    //创建一个viewController对象
    ViewController * viewController = [[ViewController alloc]init];
    
    //创建一个导航栏
    UINavigationController * navigationController = [[UINavigationController alloc]initWithRootViewController:viewController];
    
    //window的根视图
    self.window.rootViewController = navigationController;
    [self.window makeKeyAndVisible];

  
    return YES;
}

这样,高大上的地图微博就基本搞定了。收工。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值