IOS_地图_定位_天气预报_Block回调_单例

H:/1021/00_block回调.h

/*
	通过block回调
 定义block代码块,目的是解析完成之后调用
 返回值是 void
 参数是 数组,里面的每个成员是一个NSString*/

typedef void(^WeatherFinishedBlock)(NSArray *dataList);

@interface WeatherXMLPaser : NSObject
// 解析器解析数据,参数1是要解析的数据,参数2是解析完毕回调的代码块
- (void)parserWeatherData:(NSData *)data
			completion:(WeatherFinishedBlock)completion;
@end

//--------------------------------------------------------
@interface WeatherXMLPaser() <NSXMLParserDelegate>
{

	// 成员记住block代码块
    WeatherFinishedBlock  _FinishedBlock;
}
@end
//---------------------------------------------------------
#pragma mark - 成员方法
#pragma mark 解析器解析数据,参数1是要解析的数据,参数2是完毕时调用的代码块
- (void)parserWeatherData:(NSData *)data
				completion:(WeatherFinishedBlock)completion
{
    // 0. 记录块代码
    _FinishedBlock = completion;
    // 1. 实例化XML解析器
    NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];
    // 2. 设置代理为 当前的WeatherXMLPaser
    [parser setDelegate:self];
    // 3. 解析器开始解析
    [parser parse];
}
//--------------------------------------------------------
#pragma mark - XML解析代理方法,结束解析文档
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
    // 解析结束,调用代码块,参数是,解析完的成员NSString数组
	// 通过block代码块回调,通知调用方解析结果
    _FinishedBlock(_dataList);
}
//--------------------------------------------------------
// 1) 实例化单例 天气XML解析器
    WeatherXMLPaser *parser = [WeatherXMLPaser sharedWeatherXMLPaser];
	// 2)解析器解析数据,参数1是要解析的数据,参数2是解析完毕要执行的代码块
			// 并且将解析完的数组 作为参数传递进来
    [parser parserWeatherData:data completion:^(NSArray *dataList) {
		// 解析完成了,打印输出
        Weather *w = [Weather weatherWithArray:dataList];
    }];

H:/1021/00_Singleton单例.m

/*
	单例3步曲
	1,静态实例变量
	2,类方法,allocWithZone
	3,类方法,sharedXXX
*/

// 单例第1步:静态实例变量
static WeatherXMLPaser *sharedInstance;

// 单例第2步:类方法,allocWithZone
+ (id)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [super allocWithZone:zone];
    });
    return sharedInstance;
}

// 单例第3步:类方法,shared方法
+ (WeatherXMLPaser *)sharedWeatherXMLPaser
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
		// alloc方法会自动调用allocWithZone方法
        sharedInstance = [[WeatherXMLPaser alloc]init];
    });
    return sharedInstance;
}

H:/1021/01_地图_MainViewController.m

//  MainViewController.m
//  01.地图
//  Created by apple on 13-10-21.
//  Copyright (c) 2013年 itcast. All rights reserved.
/*
#import <UIKit/UIKit.h>
@interface MainViewController : UIViewController
@end
*/
#import "MainViewController.h"
#import <MapKit/MapKit.h>
//#import "MyAnnotation.h"
#import "MyAnnotation2.h"
@interface MainViewController () <MKMapViewDelegate>
{
    MKMapView *_mapView;
}
@end
@implementation MainViewController
/**
 1. 地图跟踪模式

 MKUserTrackingMode None = 0             不跟踪用户位置
 MKUserTrackingMode Follow               跟踪用户位置
 MKUserTrackingMode FollowWithHeading    带方向跟踪用户位置(汽车车头方向)

 2. 地图模式
 MKMapType Standard = 0,                 标准地图(最省电的模式)
 MKMapType Satellite,                    卫星地图
 MKMapType Hybrid                        混合地图(最费电)

 3. 设置地图显示区域,距离以米为单位(iOS7升级的,不再自动调整地图现实比例)
 MKCoordinateRegion MKCoordinateRegionMakeWithDistance

 4. 添加大头针
 addAnnotation:(id <MKAnnotation>)annotation

 凡是遵守MKAnnotation协议的对象都可以成为大头针

 5. 自定义大头针,地图视图是支持大头针视图重用的!

 如果在mapView:(MKMapView *)mapView viewForAnnotation:
									(id<MKAnnotation>)annotation
 方法中,返回nil,地图视图会使用默认的方法绘制大头针

 如果重写了mapView:viewForAnnotation方法,在程序中,调用
 addAnnotation:annotation方法时,
			annotation会以参数的形式传递给自定义大头针视图的方法

 提示:如果是自定义大头针视图,需要设置canShowCallout属性,
									才能够和视图进行交互

 6. 如果重写了mapView:viewForAnnotation方法

 跟踪用户信息时,同样会调用该方法!

 如果既要跟踪用户信息,同时又要显示大头针
 (譬如:显示汽车位置,同时显示加油站的大头针)
 如果传入的annotation不是自定义大头针视图,直接返回nil,
 使用地图默认的方法绘制大头针
 如果是自定义视图,则设置大头针属性
 */
#pragma mark - 实例化视图
- (void)loadView
{
	// 设置全屏
    self.view = [[UIView alloc]initWithFrame:[UIScreen mainScreen].applicationFrame];
    // 1. 实例化地图视图
    MKMapView *mapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
    [self.view addSubview:mapView];
	// 设置MapView的代理为当前控制器
    [mapView setDelegate:self];
    // 2. 设置跟踪用户位置的模式
    [mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
    // 3. 设置地图的类型
    [mapView setMapType:MKMapTypeHybrid];
    _mapView = mapView;
}
- (void)viewDidLoad
{
    [super viewDidLoad];
	// 根据经纬度,生成Coordinate2D坐标
    CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(+30.06055580, +116.34273116);
	// 默认大头针,通过Coordinate2D生成大头针 annotation
    MyAnnotation *annotation = [[MyAnnotation alloc]initWithCoordinate:coord title:@"我的地盘" subtitle:nil];
	// 自定义大头针,可以通过setter方法生成大头针 annotation2
    MyAnnotation2 *annotation = [[MyAnnotation2 alloc]init];
    [annotation setCoordinate:coord];
    [annotation setTitle:@"我的地盘"];
    [annotation setIcon:@"head0.png"];
    NSLog(@"%p %@", annotation, annotation);
    // 添加大头针到mapView
    [_mapView addAnnotation:annotation];
    // 自定义大头针,可以通过setter方法生成大头针 annotation2
    MyAnnotation2 *annotation2 = [[MyAnnotation2 alloc]init];
	// 根据经纬度,生成Coordinate2D坐标
    CLLocationCoordinate2D coord2 = CLLocationCoordinate2DMake(+50.06055580, +116.34273116);
    [annotation2 setCoordinate:coord2];
    [annotation2 setTitle:@"MJ"];
    [annotation2 setIcon:@"head0.png"];
    // 添加大头针到mapView
    [_mapView addAnnotation:annotation2];
    // 根据Coordinate2D坐标的经纬度,生成Location对象
    CLLocation *location1 = [[CLLocation alloc]initWithLatitude:coord.latitude longitude:coord.longitude];
	// 根据Coordinate2D坐标的经纬度,生成Location对象
    CLLocation *location2 = [[CLLocation alloc]initWithLatitude:coord2.latitude longitude:coord2.longitude];
	// 计算两个Location对象之间的距离
    CLLocationDistance distance = [location1 distanceFromLocation:location2];
    NSLog(@"两点间距离 %f", distance);
}
#pragma mark - 地图代理方法
#pragma mark 每次用户位置变化都会被调用,意味着非常费电
- (void)mapView:(MKMapView *)mapView
			didUpdateUserLocation:(MKUserLocation *)userLocation
{
    NSLog(@"%@ %@", userLocation.location, userLocation.title);
    // 利用location中的经纬度设置地图显示的坐标区域CoordinateRegion
	// 参数2,和参数3的意思是:X,Y半径
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(
							userLocation.location.coordinate, 100.0, 100.0);
    // 设置地图的显示区域,以用户所在位置为中心点,半径为100米
    [mapView setRegion:region animated:YES];
}
#pragma mark - 自定义大头针视图,参数中的annotation就是添加到mapView的大头针
- (MKAnnotationView *)mapView:(MKMapView *)mapView
					  viewForAnnotation:(id<MKAnnotation>)annotation
{
    // 如果传入的annotation不是自定义大头针视图,直接返回nil,
	// 即使用地图默认的方法绘制大头针
    // 如果是自定义视图,才要设置大头针属性,牢记~~~~
    if (![annotation isKindOfClass:[MyAnnotation2 class]]) {
        return nil;
    }
	// 同cell,标准优化代码
    static NSString *ID = @"ID";
    MKAnnotationView *view = [mapView
				dequeueReusableAnnotationViewWithIdentifier:ID];
    // 如果没有找到可重用的大头针视图,才实例化新的
    if (view == nil) {
        view = [[MKAnnotationView alloc]initWithAnnotation:annotation
										reuseIdentifier:ID];
        // 点击大头针,可以突显出来
		view.canShowCallout = YES;
    }
    // 设置大头针视图独一无二的属性
    // 1) 如果大头针视图是从缓冲池取出的,必须要重新设置大头针
    [view setAnnotation:annotation];
    // 2) 设置大头针图像,需手动转成MyAnnotation2 *,才能使用子类的特有属性
    [view setImage:[UIImage imageNamed:((MyAnnotation2 *)annotation).icon]];
    return view;
}
@end

H:/1021/01_地图_MyAnnotation.m

//  MyAnnotation.m
//  01.地图
//  Created by apple on 13-10-21.
//  Copyright (c) 2013年 itcast. All rights reserved.
/*
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
// 大头针,遵守协议 <MKAnnotation>
@interface MyAnnotation : NSObject <MKAnnotation>
// 提示,因为要给对象属性赋值,所以此处实例化对象方法不能用工厂方法,
		原因就是类方法中,无法访问对象的成员变量
// 坐标,标题,子标题
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate
					title:(NSString *)title subtitle:(NSString *)subtitle;
@end
*/
#import "MyAnnotation.h"
@interface MyAnnotation()
{
    CLLocationCoordinate2D  _coordinate;
    NSString                *_title;
    NSString                *_subtitle;
}
@property (strong, nonatomic) NSString *strong_str1;
@property (copy, nonatomic) NSString *copy_str2;
@end
@implementation MyAnnotation
/*
 copy   copy常用于NSString,目的是改变新的不影响旧的
		copy出来的对象是不可变对象,
		而mutableCopy出来的是可变对象
		因此,只有对不可变对象进行copy的时候,相当于retain

		属性是非arc的,但是在arc中同样可以使用,表示对象是可以复制的
        使用copy描述符,在给对象赋值时,会建立对象的副本

        在非arc开发中,字符串类型NSString通常使用copy描述符

        copy属性通常被称为深复制
 strong 属于arc的,在非arc中不可以使用,等同于非arc中的retain
        使用strong描述符,在给对象赋值时,会建立对象的指针副本

        strong属性通常被称为浅复制

        在性能上strong会略微比copy要好,建议大家在日常开发中使用strong。
 */
- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate
					title:(NSString *)title subtitle:(NSString *)subtitle
{
    if (self = [super init]) {
		// 为成员赋值
        _coordinate = coordinate;
        _title = title;
        _subtitle = subtitle;

        NSMutableString *string = [NSMutableString string];
        [string setString:@"oldValue"];
        // strong 浅拷贝,只是建立指针副本
        self.strong_str1 = string;
		// copy 深拷贝,建立对象副本
        self.copy_str2 = string;
		// 因此,string和strong_str1两个指针指向的是同一个地址
		// 而copy_str2指向的是一个新的地址(新复制的对象的地址)
        NSLog(@"%p %p %p", string, self.strong_str1, self.copy_str2);

        [string setString:@"newValue"];
		// string和strong_str1指向同一个,故结果是newValue
		// copy_str2指向的是一个新开的地址,故结果依然是oldValue
        NSLog(@"%@ %@ %@", string, self.strong_str1, self.copy_str2);
    }
    return self;
}
#pragma mark - 只读属性,即只有getter方法
- (CLLocationCoordinate2D)coordinate
{
    return _coordinate;
}
- (NSString *)title
{
    return _title;
}
- (NSString *)subtitle
{
    return _subtitle;
}
@end

H:/1021/01_地图_MyAnnotation2.h

//
//  MyAnnotation2.h
//  01.地图
//
//  Created by apple on 13-10-21.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
// 自定义大头针,遵守协议 <MKAnnotation>
@interface MyAnnotation2 : NSObject <MKAnnotation>
// 坐标,标题,副标题
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;

// 大头针图标的名字
@property (nonatomic, strong) NSString *icon;

@end

H:/1021/02_定位_MainViewController.m

//  MainViewController.m
//  02.定位
//  Created by apple on 13-10-21.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "MainViewController.h"
#import <CoreLocation/CoreLocation.h>
@interface MainViewController () <CLLocationManagerDelegate>
{
	// 成员:LocationManager定位管理器
    CLLocationManager   *_locationManager;
	// 成员:Geocoder 地理位置编码器
    CLGeocoder          *_geocoder;
}
@end
@implementation MainViewController
/*
 1. 要使用定位服务,都是从CLLocationManager开始的

 2. 在实际应用开发中,需要判断用户的定位服务是否打开,
	如果没有打开,需要提示用户
    直接用定位管理器的类方法locationServicesEnabled可以判断。

 3. 在大多数情况下CLLocation的精度不如MKMapView高,但是因为不使用UIMapView,
    相对性能较好!

 4. 使用CLLocation时,最好设置定位精度,以省电

 kCLLocationAccuracy Best;               // 最佳精度(最耗电)
 kCLLocationAccuracy NearestTenMeters;   // 最近10米范围内定位
 kCLLocationAccuracy HundredMeters;      // 百米
 kCLLocationAccuracy Kilometer;          // 千米
 kCLLocationAccuracy ThreeKilometers;    // 3000米

    使用startUpdatingLocation可以开始定位用户位置
    如果不需要持续跟踪用户的行踪,定位之后,
	最好stopUpdatingLocation替用户省电!

 5. 根据经纬度计算地名

 - (void)reverseGeocodeLocation:(CLLocation *)location
		  completionHandler:(CLGeocodeCompletionHandler)completionHandler;

 6. 根据地名计算经纬度

 - (void)geocodeAddressString:(NSString *)addressString
			completionHandler:(CLGeocodeCompletionHandler)completionHandler;
 */
- (void)viewDidLoad
{
    [super viewDidLoad];
    // 1. 判断定位服务是否可用
    if ([CLLocationManager locationServicesEnabled]) {
        // 1) 实例化定位管理器
        _locationManager = [[CLLocationManager alloc]init];
        // 2) 设置定位管理器的代理,当位置变化时,会调用代理的方法
        [_locationManager setDelegate:self];
        // 3) 设置定位管理器的精度
        [_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
        // 4) 开启用户定位功能
        [_locationManager startUpdatingLocation];

        // 5) 实例化geocoder
        _geocoder = [[CLGeocoder alloc]init];
        // 根据地名,反向解析出坐标
        [_geocoder geocodeAddressString:@"西湖"
				completionHandler:^(NSArray *placemarks, NSError *error) {
            // placemarks 地点、地标
            CLPlacemark *placemark = placemarks[0];
            NSLog(@"%@ %@", placemark.location, placemark.country);
        }];
    } else {
        NSLog(@"没有开启定位服务");
    }
}
#pragma mark - 定位管理器代理方法
#pragma mark 更新位置,只要用户的位置发生变化,就会被调用,非常费电!
- (void)locationManager:(CLLocationManager *)manager
							didUpdateLocations:(NSArray *)locations
{
	// 数组locations中只有一个位置
    NSLog(@"%@", locations[0]);
	// 根据地名,反向解析出坐标
    [_geocoder reverseGeocodeLocation:locations[0]
			   completionHandler:^(NSArray *placemarks, NSError *error) {
        // placemarks 地点、地标
        CLPlacemark *placemark = placemarks[0];
		// 中国北京市昌平区回龙观地区建材城西路67号
        NSLog(@"%@", placemark);
    }];
}
@end

H:/1021/03_天气预报_MainViewController.m

//  MainViewController.m
//  03.天气预报
//  Created by apple on 13-10-21.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "MainViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "WeatherXMLPaser.h"
#import "Weather.h"
#import "WeatherAnnonation.h"
/*
	天气预报项目流程
	1,POST请求抓起网络数据
	2,XML解析response的数据
	3,MapView
	4,XML返回的地址信息,利用Geocoder地理编码器获得经纬度,设置大头针位置
	5,XML中的图片名作大头针annotation的自定义image
	6,大头针的title显示城市名和温度和空气质量PM2.5 PM10
	7,大头针的subtitle显示天气详情
*/
@interface MainViewController () <MKMapViewDelegate>
{
    // 操作队列
    NSOperationQueue    *_queue;
    // 地图视图
    MKMapView           *_mapView;
    // 地理编码器
    CLGeocoder          *_geocoder;
}
@end
@implementation MainViewController
/*
 在开发网络应用时,通常服务器考虑到负载的问题,会禁止同一个地址,
 连续多次提交请求

 大多数这种情况下,服务器只响应一次!

 解决办法:隔一秒抓一次!

 思路:

 1) 抓取城市天气信息的数据,不能够并发执行,要开个新线程,即在background运行
	需要依次执行=>NSURLConntection需要发送同步请求
 2) 如果单纯使用同步请求,会阻塞主线程,影响用户体验
 3) 新开一个线程,在后台依次抓取所有城市的数据
 */
#pragma mark - 实例化视图
- (void)loadView
{
    self.view = [[UIView alloc]initWithFrame:[UIScreen mainScreen].applicationFrame];
    _mapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
    // 1. 如果需要旋转屏幕,同时自动调整视图大小
    [_mapView setAutoresizingMask:UIViewAutoresizingFlexibleHeight |
										UIViewAutoresizingFlexibleWidth];
    // 2. 添加到根视图
    [self.view addSubview:_mapView];
    // 3. 设置mapView的代理 为当前控制器
    [_mapView setDelegate:self];
}
#pragma mark - 加载数据
- (void)viewDidLoad
{
    [super viewDidLoad];
    _queue = [[NSOperationQueue alloc]init];
    _geocoder = [[CLGeocoder alloc]init];
    // 在后台线程加载城市数据
    [self performSelectorInBackground:@selector(loadWeatherData)
									  withObject:nil];
}
#pragma mark 自定义方法,加载城市天气数据,后台运行
- (void)loadWeatherData
{
    NSLog(@"%@", [NSThread currentThread]);
    [self loadWeatherDataWithCityName:@"北京"];
    [NSThread sleepForTimeInterval:1.0f];
    [self loadWeatherDataWithCityName:@"重庆"];
    [NSThread sleepForTimeInterval:1.0f];
    [self loadWeatherDataWithCityName:@"上海"];
}
#pragma mark 自定义方法,POST请求,抓取网络天气数据
- (void)loadWeatherDataWithCityName:(NSString *)cityName
{
    // 1. NSURL
    NSString *urlString = @"http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getWeatherbyCityName";
    NSURL *url = [NSURL URLWithString:urlString];
    // 2. NSMutableURLRequest,POST请求
    NSMutableURLRequest *request = [NSMutableURLRequest
							requestWithURL:url
							cachePolicy:NSURLRequestUseProtocolCachePolicy
							timeoutInterval:2.0f];
    // 1) 指定数据体
    NSString *bodyString = [NSString stringWithFormat:@"theCityName=%@",
														cityName];
	// 中文必须转码 NSUTF8StringEncoding
    NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
	// 设置请求体
    [request setHTTPBody:bodyData];
    // 2) 指定http请求方式
    [request setHTTPMethod:@"POST"];
    // 3. NSURLConnection,同步请求,response用于接收返回的内容
    NSURLResponse *response = nil;
    NSData *data = [NSURLConnection sendSynchronousRequest:request
					returningResponse:&response error:nil];
    // 1) 实例化单例 天气XML解析器
    WeatherXMLPaser *parser = [WeatherXMLPaser sharedWeatherXMLPaser];
    // 2) 解析
    [parser parserWeatherData:data completion:^(NSArray *dataList) {
		// 解析完成的回调方法中,填充Model
        Weather *w = [Weather weatherWithArray:dataList];
        // 根据城市名称,使用地理编码器获取到对应的经纬度,然后设置大头针的位置
        [_geocoder geocodeAddressString:w.cityName
				completionHandler:^(NSArray *placemarks, NSError *error) {
            // 地标有个location成员,location里面有2D坐标
            CLPlacemark *placemark = placemarks[0];
            // 大头针安插在此
            WeatherAnnonation *annonation = [[WeatherAnnonation alloc]init];
            // 指定大头针的经纬度位置
            annonation.coordinate = placemark.location.coordinate;
            annonation.title = [NSString stringWithFormat:@"%@ %@", w.cityName, w.temperature];
            annonation.subtitle = [NSString stringWithFormat:@"%@ %@", w.todayInfo, w.wind];
            annonation.imageName = w.imageName;
            [_mapView addAnnotation:annonation];
        }];
    }];
}
#pragma mark - 地图视图代理方法,viewForAnnotation
- (MKAnnotationView *)mapView:(MKMapView *)mapView
			viewForAnnotation:(id<MKAnnotation>)annotation
{
	// 要判断isKindOfClass,如果不是自定义的,就用默认的,即return nil
	// 如果传入的annotation不是自定义大头针视图,直接返回nil,
	// 即使用地图默认的方法绘制大头针
    // 如果是自定义视图,才要设置大头针属性,牢记~~~~
    if (![annotation isKindOfClass:[WeatherAnnonation class]]) {
        return nil;
    }
    static NSString *ID = @"ID";
    MKAnnotationView *view = [mapView
				dequeueReusableAnnotationViewWithIdentifier:ID];
    if (view == nil) {
        view = [[MKAnnotationView alloc]initWithAnnotation:annotation
												reuseIdentifier:ID];
		// 设置大头针,可以被点击后呼出
        view.canShowCallout = YES;
    }
    // 设置大头针视图独一无二的属性
    // 1) 如果大头针视图是从缓冲池取出的,必须要重新设置大头针
    view.annotation = annotation;
    // 设置图像
	// 2) 设置大头针图像,需手动转成WeatherAnnonation *,才能使用子类的特有属性
    [view setImage:[UIImage imageNamed:((WeatherAnnonation *)annotation).icon]];
    return view;
}
@end

H:/1021/03_天气预报_Weather.m

//  Weather.m
//  03.天气预报
//  Created by apple on 13-10-21.
/*
//  Weather.h
//  03.天气预报
#import <Foundation/Foundation.h>
@interface Weather : NSObject
#pragma mark 工厂方法
+ (Weather *)weatherWithArray:(NSArray *)array;
// 1. 城市名
@property (strong, nonatomic) NSString *cityName;
// 2. 今天的信息
@property (strong, nonatomic) NSString *todayInfo;
// 3. 风向
@property (strong, nonatomic) NSString *wind;
// 4. 图片名
@property (strong, nonatomic) NSString *imageName;
// 5. 气温
@property (strong, nonatomic) NSString *temperature;
@end

*/
#import "Weather.h"
@implementation Weather
+ (Weather *)weatherWithArray:(NSArray *)array
{
    Weather *w = [[Weather alloc]init];
    w.cityName = array[1];
    w.todayInfo = array[6];
    w.wind = array[7];
    w.imageName = array[8];
    w.temperature = array[5];
    return w;
}
// 重写toString方法
- (NSString *)description
{
    return [NSString stringWithFormat:
			@"<Weather: %p, cityName: %@, todayInfo: %@, wind: %@,
			imageName: %@, temperature: %@>",
			self, self.cityName, self.todayInfo,
			self.wind, self.imageName, self.temperature];
}
@end

H:/1021/03_天气预报_WeatherAnnonation.h

//  WeatherAnnonation.h
//  03.天气预报
//  Created by apple on 13-10-21.
//  Copyright (c) 2013年 itcast. All rights reserved.

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface WeatherAnnonation : NSObject <MKAnnotation>
// 覆盖协议里面的成员,坐标,标题,副标题,图片名
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;
@property (strong, nonatomic) NSString *imageName;
@end

H:/1021/03_天气预报_WeatherXMLPaser.h

//  WeatherXMLPaser.h
//  03.天气预报
//  Created by apple on 13-10-21.
#import <Foundation/Foundation.h>
/*
 定义block代码块,目的是解析完成之后调用
 返回值是 void
 参数是 数组,里面的每个成员是一个NSString
*/

typedef void(^WeatherFinishedBlock)(NSArray *dataList);

@interface WeatherXMLPaser : NSObject

// 单例,返回解析器对象
+ (WeatherXMLPaser *)sharedWeatherXMLPaser;
// 解析器解析数据,参数1是要解析的数据,参数2是解析完毕回调的代码块
- (void)parserWeatherData:(NSData *)data
			completion:(WeatherFinishedBlock)completion;
@end

H:/1021/03_天气预报_WeatherXMLPaser.m

//  WeatherXMLPaser.m
//  03.天气预报
//  Created by apple on 13-10-21.
/*
	天气预报项目流程
	1,POST请求抓起网络数据
	2,XML解析response的数据
	3,MapView
	4,XML返回的地址信息,利用Geocoder地理编码器获得经纬度,设置大头针位置
	5,XML中的图片名作大头针annotation的自定义image
	6,大头针的title显示城市名和温度和空气质量PM2.5 PM10
	7,大头针的subtitle显示天气详情
*/
#import "WeatherXMLPaser.h"
// 单例第1步:静态实例变量
static WeatherXMLPaser *sharedInstance;
// 要想解析XML 必须遵守协议<NSXMLParserDelegate>
@interface WeatherXMLPaser() <NSXMLParserDelegate>
{

	// 自定义block代码块
    WeatherFinishedBlock  _FinishedBlock;
    // 解析结果的字符串数组,根节点是<ArrayOfString>,其余节点名全是<String>
    NSMutableArray          *_dataList;
	// 临时文本字符串
    NSMutableString         *_tempStr;
}
@end
@implementation WeatherXMLPaser
/*  单例模板写法
 1. 静态实例变量   static WeatherXMLPaser *sharedInstance;
 2. allocWithZone
 3. shared方法*/

#pragma mark - 单例方法
// 单例第2步:类方法,allocWithZone
+ (id)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [super allocWithZone:zone];
    });
    return sharedInstance;
}
// 单例,返回解析器对象
// 单例第3步:类方法,shared方法
+ (WeatherXMLPaser *)sharedWeatherXMLPaser
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[WeatherXMLPaser alloc]init];
    });
    return sharedInstance;
}
#pragma mark - 成员方法
#pragma mark 解析器解析数据,参数1是要解析的数据,参数2是完毕时调用的代码块
- (void)parserWeatherData:(NSData *)data
				completion:(WeatherFinishedBlock)completion
{
    // 0. 记录块代码
    _FinishedBlock = completion;
    // 1. 实例化XML解析器
    NSXMLParser *parser = [[NSXMLParser alloc]initWithData:data];
    // 2. 设置代理为 当前的WeatherXMLPaser
    [parser setDelegate:self];
    // 3. 解析器开始解析
    [parser parse];
}
#pragma mark - XML解析代理方法
#pragma mark 5. 结束解析文档
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
    // 解析结束,调用代码块,参数是,解析完的NSString数组
	// 通过block代码块回调,通知调用方解析结果
    _FinishedBlock(_dataList);
}
#pragma mark 2. 开始解析元素节点
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
					namespaceURI:(NSString *)namespaceURI
					qualifiedName:(NSString *)qName
					attributes:(NSDictionary *)attributeDict
{
	// 根节点是<ArrayOfString>,其余节点名全是<String>
	// 如果节点名是ArrayOfString,说明是根节点,准备好数组_dataList,装数据
    if ([elementName isEqualToString:@"ArrayOfString"]) {
        if (_dataList) {
            [_dataList removeAllObjects];
        }
    }
    // 无论是什么节点开始了,都要将临时文本清空,用于拼装文本节点
    [_tempStr setString:@""];
}
#pragma mark 4. 结束解析节点,重点
- (void)parser:(NSXMLParser *)parser
				didEndElement:(NSString *)elementName
				namespaceURI:(NSString *)namespaceURI
				qualifiedName:(NSString *)qName
{
	// 根节点是<ArrayOfString>,其余节点名全是<String>
    NSString *result = [NSString stringWithString:_tempStr];
	// 如果结束的节点是</String>,就把拼装好的文本节点,添加到数组_dataList
    if ([elementName isEqualToString:@"string"]) {
        [_dataList addObject:result];
    }
}
#pragma mark 1. 开始解析文档,初始化准备工作
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
    // 懒加载临时文本字符串
    if (_tempStr == nil) {
        _tempStr = [NSMutableString string];
    }
    // 懒加载结果数组
    if (_dataList == nil) {
        _dataList = [NSMutableArray array];
    }
}
#pragma mark 6. 解析出错
- (void)parser:(NSXMLParser *)parser
			parseErrorOccurred:(NSError *)parseError
{
    NSLog(@"解析出错 %@", parseError.localizedDescription);
	// 置空临时文本
    [_tempStr setString:@""];
}
#pragma mark 3. 发现文本内容(一个文本节点可能会解析多次)
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    // 追加文本
    [_tempStr appendString:string];
}
@end

IOS_地图_定位_天气预报_Block回调_单例,布布扣,bubuko.com

时间: 2024-10-11 07:32:23

IOS_地图_定位_天气预报_Block回调_单例的相关文章

IOS_地图与定位

知识点介绍 一. 定位 实现一次定位 CLLocation对象介绍 实现持续定位 请求用户授权 二. 地理编码 正地理编码 反地理编码 三. 地图的基本使用 显示用户位置 设置地图显示类型 根据用户位置显示对应的大头针信息 设置以用户所在位置为中心点 监听地图显示区域改变 iOS9新特性-显示交通状况 / 显示比例 / 显示指南针 四. 大头针的使用 添加大头针 自定义大头针1, 更改颜色, 设置掉落效果 自定义大头针2-更改大头针的图像 自定义大头针的代码封装 一. CoreLocation实

iOS进阶_地图上定位的标志——大头针

一.添加大头针 地图使用的框架是MapKit 大头针走的是MKAnnotation协议 /* 注意:因为是满足协议MKAnnotation,所以没有MKAnnotation的系统大头针类,必须自定义大头针类,我自定义的为MyAnnotation 大头针: 在iOS开发中经常会标记某个位置,需要使用地图标注,也就是大家俗称的“大头针”.只要一个NSObject类实现MKAnnotation协议就可以作为一个大头针,通常会重写协议中coordinate(标记位置).title(标题).subtitl

通过jstack定位在线运行java系统故障_案例1

问题描述: 在一个在线运行的java web系统中,会定时运行一个FTP上传的任务,结果有一天发现,文件正常生成后却没有上传. 问题初步分析: 1.查看日志文件 发现这个任务只打印了开始进入FTP处理的日志,但是没有打印FTP处理完成的日志. 从代码上看,FTP上传处理的代码异常保护都非常的好,如果出现异常,就会进行打印,而日志文件中却没有相关的信息,甚是奇怪.怀疑是FTP过程问题,如对方FTP服务器有什么问题导致,但是却找不到证据. 苦于无法窥探java运行系统内部信息,祭出杀手锏-jstac

Android应用中使用百度地图API定位自己的位置(二)

官方文档:http://developer.baidu.com/map/sdkandev-6.htm#.E7.AE.80.E4.BB.8B3 百度地图SDK为开发者们提供了如下类型的地图覆盖物: 我的位置图层(MyLocationOverlay):用于显示用户当前位置的图层(支持自定义位置图标): Poi搜索结果图层(PoiOverlay):用于显示兴趣点搜索结果的图层: 路线图层(RouteOverlay):公交.步行和驾车线路图层,将公交.步行和驾车出行方案的路线及关键点显示在地图上(起.终

Android Studio之高德地图实现定位和3D地图显示

在应用开发中,地图开发是经常需要使用的"组件",国内比较出名的是就是百度地图和高德地图. 此博客讲的是高德地图实现定位和3D地图显示,并标注相应位置,话不多说,先看看效果,在上代码. 效果如图: 首先注册高德成为开发者(打开高德地图,点击底部的开发者平台),创建应用,按照要求填写相应信息,如下图: 途中包含了发布版的SHA1安全码和测试版SHA1安全码,两者的值可以看  博客 :Android Studio apk打包,keystore.jks文件生成,根据keystore密钥获取SH

iOS开发之地图与定位

---恢复内容开始--- 地图和定位看上去是挺高大上一东西,其实用法比TableView简单多了,下面的Demo是用的iOS中自带的地图和定位,当然了也可以用第三方的来加载地图,比如百度地图啥的,在这就不赘述了.今天的博客主要是介绍MKMapView的使用,MapView的使用和其他组件的用法差不多,MapView用的是委托回调,在使用mapView的Controller中要实现MKMapViewDelegate协议,并注册委托回调,然后实现相应的回调方法即可. 一,构建Demo的组件 为了节省

百度地图和定位

1 package com.example.administrator.yunstore; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.util.Log; 6 import android.widget.TextView; 7 8 import com.baidu.location.BDLocation; 9 import com.baidu.location.BDLocationLi

iOS开发--地图与定位

概览 现在很多社交.电商.团购应用都引入了地图和定位功能,似乎地图功能不再是地图应用 和导航应用所特有的.的确,有了地图和定位功能确实让我们的生活更加丰富多彩,极大的改变了我们的生活方式.例如你到了一个陌生的地方想要查找附近的酒 店.超市等就可以打开软件搜索周边;类似的,还有很多团购软件可以根据你所在的位置自动为你推荐某些商品.总之,目前地图和定位功能已经大量引入到应用开 发中.今天就和大家一起看一下iOS如何进行地图和定位开发. 定位 地图 定位 要 实现地图.导航功能,往往需要先熟悉定位功能

iOS开发系列--地图与定位

概览 现在很多社交.电商.团购应用都引入了地图和定位功能,似乎地图功能不再是地图应用和导航应用所特有的.的确,有了地图和定位功能确实让我们的生活更加丰富多彩,极大的改变了我们的生活方式.例如你到了一个陌生的地方想要查找附近的酒店.超市等就可以打开软件搜索周边;类似的,还有很多团购软件可以根据你所在的位置自动为你推荐某些商品.总之,目前地图和定位功能已经大量引入到应用开发中.今天就和大家一起看一下iOS如何进行地图和定位开发. 定位 地图 定位 要实现地图.导航功能,往往需要先熟悉定位功能,在iO