参考网址:
经纬度定位:http://blog.csdn.net/whaomian/article/details/6807739
位置解析:http://www.cocoachina.com/bbs/read.php?tid=134893&keyword=%B5%D8%C0%ED%CE%BB%D6%C3
百度天气免费API:http://www.cnblogs.com/txw1958/p/baidu-weather-forecast-api.html
AFNetworking访问网络和简单JSON解析:http://e673.com/index.php/afnetworking-conclu-json/
解决URL中中文编码不被识别:http://blog.csdn.net/typingios/article/details/9136005
最近心血来潮,就想学习一下定位和获取天气。刚开始感觉挺难的,做下来花费了将近四天的时间,收货颇多。像我这种新手,刚开始是有需求但不知道怎么实现,很多时间都花费在找资料上了。其实熟练了就几不花时间了。
进入正题:
1.定位。
首先在项目中加入库CoreLocaltion.framework。单单是定位的话,用CoreLocaltion.framework和mapkit.framework是没有区别的,但是mapkit.framework支持地图方面的扩展也更臃肿。
在.h文件中加入引用:
1 #import <CoreLocaltion/CoreLocaltion.h>
实现代理:CLLocationManagerDelegate
并定义两个变量:
1 CLLocationManager *localManager; 2 CLLocation *newLocation;
在.m文件中的viewDidLoad方法中初始化localManager并设置代理为自己:
1 //初始化LocationManager 2 locationManager = [[CLLocationManager alloc] init]; 3 //设置定位精度 4 locationManager.desiredAccuracy = kCLLocationAccuracyBest; 5 //设置代理 6 locationManager.delegate = self;
并实现方法locationManager:didUpdateLocations:,用于在定位成功时进行处理事务
1 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations 2 { 3 newLocation = [locations firstObject];//第一个是当前的位置,第二个是原先的位置 4 5 //定位成功后的处理,如显示到视图中去 6 //纬度:newLocation.coordinate.latitude, 经度:newLocation.coordinate.longitude 7 8 [localManager stopUpdatingLocation];//关闭定位 9 }
顺便提一下以前的方法locationManager:didUpdateToLocation:fromLocation:,建议用上面的新的方法!
1 - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { 2 newLocation = newLocation; 3 //定位成功后的处理,如上 4 }
上面的方法从函数名上应该能看出来,是位置更新后自动调用的方法,但是位置更新却是要程序控制的,比如,程序中的一个按钮被点击时开始更新位置,则要在点击事件中加入对定位服务的判断和对更新位置的请求:
1 if ([CLLocationManager locationServicesEnabled]) { 2 //如果是iOS8的话则要手动请求一下定位的授权 3 if (CurrentVesion >= 8.0) { 4 [locationManager requestWhenInUseAuthorization]; 5 } 6 //更新位置 7 [locationManager startUpdatingLocation]; 8 }else{ 9 //给出提示,定位服务不可用或没有授权获取位置信息 10 }
2.解析位置
刚只是获取了位置信息,下面来对位置信息(上面定义的location)进行解码,这样就可以得到位置信息的文字描述,如“河南省开封市金明区***街道***号”。
在.h文件中加入一个变量:CLPlacemark *placemark;//这里不是特别必要非要在这里建这个变量,但是后面通过天气API获取天气数据要用到
在.m文件中,开始进行解码。可加到上面“定位成功后的处理”部分:
1 //位置的文字串描述 2 __block NSString *locationInfo = @""; 3 4 CLGeocoder *geocoder = [[CLGeocoder alloc] init]; 5 [geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) { 6 if (placemarks.count > 0) { 7 placemark = [placemarks objectAtIndex:0]; 8 9 locationInfo = [[placemark.addressDictionary valueForKey:@"FormattedAddressLines"] componentsJoinedByString:@", "]; 10 11 //打印placemark的各个字段信息 12 NSLog(@"I am currently at %@",locationInfo); 13 NSLog(@"placemark.ISOcountryCode %@",placemark.ISOcountryCode); 14 NSLog(@"placemark.country %@",placemark.country); 15 NSLog(@"placemark.postalCode %@",placemark.postalCode); 16 NSLog(@"placemark.administrativeArea %@",placemark.administrativeArea); 17 NSLog(@"placemark.locality %@",placemark.locality); 18 NSLog(@"placemark.subLocality %@",placemark.subLocality); 19 NSLog(@"placemark.subThoroughfare %@",placemark.subThoroughfare); 20 } 21 }];
3.使用天气接口获取天气
在网上搜了好久的天气接口,发现还是百度的好用(稳定,免费),就果断用了百度。
使用接口时要访问网络获取数据的,所以这里还要注意联网的。网上说AFNetworking不错,也是果断用了,先实现出来再挑好坏。
在AFNetworking官网下载好zip包,把其中的AFNetworking文件夹加入到项目中去。
在.h文件中加入引用:
1 #import "AFHTTPRequestOperation.h"
添加变量:
1 //存储结构化的天气数据,为了程序中复用,建议使用Model,然后方便操作再封上一层ModelService 2 NSDictionary *responseDic;
然后在设置参数请求数据(如在另一个button事件中):
1 //注意参数“ak”后面的数据在自己做应用时一定自己去百度申请 2 //参数“location”,有说能用经纬度的,但是我测试失败,不知道是不是我当时处理时写错了 3 //参数“output”,指定返回数据类型,json或者xml 4 5 //链接字符串 6 NSString *RequestStr = [NSString stringWithFormat:@"http://api.map.baidu.com/telematics/v3/weather?location=%@&output=json&ak=******", placemark.locality]; 7 //链接字符串,utf8格式,这个我在另一个demo中没有特意设置为utf8也正常使用 8 NSString *weatherRequestStr = [RequestStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 9 //URL链接 10 NSURL *weatherRequestUrl = [NSURL URLWithString:weatherRequestStr]; 11 //请求 12 NSURLRequest *weatherRequest = [NSURLRequest requestWithURL:weatherRequestUrl]; 13 14 //AF库提供的请求操作,初始化 15 AFHTTPRequestOperation *weatherRequestOperation = [[AFHTTPRequestOperation alloc]initWithRequest:weatherRequest]; 16 //设置请求操作成功和失败的回调函数 17 [weatherRequestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject){ 18 NSLog(@"请求成功!"); 19 20 //用NSJSONSerialization解析JSON 21 NSString *responseStr = [NSString stringWithString:operation.responseString]; 22 NSLog(@"%@", responseStr); 23 NSData *responseData = [[NSData alloc] initWithData:[responseStr dataUsingEncoding:NSUTF8StringEncoding]]; 24 responseDic = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:nil]; 25 } failure:^(AFHTTPRequestOperation *operation, NSError *error){ 26 NSLog(@"请求失败: %@", error); 27 }]; 28 //开始请求操作 29 [weatherRequestOperation start];
4.解析天气数据
得到结构化的天气数据后,就可以进行数据读取了,这里采用的是JSON。JSON的解析其实就是对NSArray和NSDictionary的取值操作。建议封装到相应Model的Service中去,方便使用。
初学者注意一下:在存取数据时一定要仔细分析JSON(XML)的结构,否则你会耗好久时间找错误,中间可能还会以为是函数方法写错误了。在JSON文件中,“{”和“}”中间的数据是NSDictionary类型的数据,“[”和“]”中间的数据是NSArray类型的,特别是当好几个“{”或“}”和“[”或“]”挨着时,一定分析好再写。
OK,至此,就可以写一个自己的天气小应用了。