最终效果图:
右下角的回到用户位置按钮:
MapController控制器,
是主控制器左侧dock上面的【地图】按钮对应的控制器,
继承自ShowDealDetailController,
因此,自动拥有了展示团购详情控制器的功能
// // MapController.h // 帅哥_团购 // // Created by beyond on 14-8-14. // Copyright (c) 2014年 com.beyond. All rights reserved. // dock上面的【地图】按钮对应的控制器,继承自ShowDealDetailController.h控制器,自动拥有了展示团购详情控制器的功能了 #import "ShowDealDetailController.h" @interface MapController : ShowDealDetailController @end
// // MapController.m // 帅哥_团购 // // Created by beyond on 14-8-14. // Copyright (c) 2014年 com.beyond. All rights reserved. // dock上面的【地图】按钮对应的控制器,继承自ShowDealDetailController.h控制器,自动拥有了展示团购详情控制器的功能了 #import "MapController.h" #import <MapKit/MapKit.h> #import "DealRequestTool.h" #import "MetaDataTool.h" #import "LocationTool.h" // 成员有经纬度坐标 #import "City.h" // 一个商户模型 #import "Business.h" #import "Deal.h" // 一个大头针模型,为大头针View提供数据源的 #import "MyAnnotation.h" // 跨的经度和纬度 #define kSpan MKCoordinateSpanMake(0.018404, 0.031468) @interface MapController ()<MKMapViewDelegate> { MKMapView *_mapView; NSMutableArray *_showingDeals; } @end @implementation MapController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"地图"; // 0.监听定位完成的通知.....这里面有问题 kAddAllNotes(dataChange) // 1.添加地图 MKMapView *mapView = [[MKMapView alloc] initWithFrame:self.view.bounds]; mapView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; // 显示用户的位置点 mapView.showsUserLocation = YES; // 设置代理 mapView.delegate = self; [self.view addSubview:mapView]; // 2.初始化数组 _showingDeals = [NSMutableArray array]; // 3.添加回到用户位置的按钮 [self addBackToUserLocationBtn]; } - (void)addBackToUserLocationBtn { // 3.添加回到用户位置的按钮 UIButton *backUserBtn = [UIButton buttonWithType:UIButtonTypeCustom]; CGSize imgSize = [backUserBtn setBtnBgImgForNormal:@"btn_map_locate.png" highlightedName:@"btn_map_locate_hl.png"]; CGFloat w = imgSize.width; CGFloat h = imgSize.height; CGFloat margin = 20; CGFloat x = self.view.frame.size.width - w - margin; CGFloat y = self.view.frame.size.height - h - margin; // 按钮处于右下角所以左边距和上边距自动伸缩 backUserBtn.frame = CGRectMake(x, y, w, h); backUserBtn.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin; [backUserBtn addTarget:self action:@selector(backToUserLocationBtnClicked) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:backUserBtn]; } // 返回到用户中心点按钮被点击 - (void)backToUserLocationBtnClicked { // mapView里面保存着用户的位置信息(The annotation representing the user's location) CLLocationCoordinate2D center = _mapView.userLocation.location.coordinate; MKCoordinateRegion region = MKCoordinateRegionMake(center, kSpan); // 设置中心点 [_mapView setRegion:region animated:YES]; } #pragma mark - mapView的代理方法 #pragma mark 当定位到用户的位置就会调用(调用频率相当高)---2 - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { // 只让它首次定位到用户坐标 if (_mapView) return; // 1.用户位置的(中心点) CLLocationCoordinate2D center = userLocation.location.coordinate; // 2.确定好中心点之后,再确定跨度(范围) // MKCoordinateSpan span = MKCoordinateSpanMake(0.018404, 0.031468); // 3.根据中心点和跨度之后,就确定好了区域 MKCoordinateRegion region = MKCoordinateRegionMake(center, kSpan); // 4.让mapView显示到指定的区域 [mapView setRegion:region animated:YES]; _mapView = mapView; // 设置中心点坐标 为用户的坐标... // [mapView setCenterCoordinate:userLocation.location.coordinate animated:YES]; } #pragma mark 拖动地图(地图展示的区域改变了)就会调用 - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated { // 1.地图当前展示区域的中心位置 CLLocationCoordinate2D pos = mapView.region.center; // 根据中心点位置坐标,反算出城市名, // 2.利用工具类向服务器发送请求 [[DealRequestTool sharedDealRequestTool] dealsRequestWithPos:pos success:^(NSArray *deals, int total_count) { // 遍历返回的deals数组,并与当前控制器保存的已经显示过的deals数组比较,如果,已经显示过该deal,则continue跳过, for (Deal *d in deals) { // 已经显示过,跳过,避免 大头针 影子加深 if ([_showingDeals containsObject:d]) continue; // 如果返回的deal,从未显示过,先加到成员数组中,然后,将该团购的成员:商区,一一用大头针进行显示到mapView上面 [_showingDeals addObject:d]; // 遍历 该团购的商户对象数组 for (Business *b in d.businesses) { // 一个商户对应一个大头针模型,也就是数据源,为Annotation View提供数据 // Annotation 是 模型,用来在map上标记 坐标 // 实现代理的 mapView:viewForAnnotation: 方法,返回每一个Annotation对应的Annotation View MyAnnotation *anno = [[MyAnnotation alloc] init]; anno.business = b; anno.deal = d; anno.coordinate = CLLocationCoordinate2DMake(b.latitude, b.longitude); // 重要~~~ 为mapView提供数据,接着会来到方法mapView:viewForAnnotation: [mapView addAnnotation:anno]; } } } error:^(NSError *error) { log(@"error---%@",error); }]; } #pragma mark - mapView的代理方法 // 类似于 cell For Row,为每一个annotation 提供view,这里使用了自定义的Annotation模型 - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(MyAnnotation *)annotation { if (![annotation isKindOfClass:[MyAnnotation class]]) return nil; // 1.从缓存池中取出大头针view static NSString *ID = @"MKAnnotationView"; MKAnnotationView *annoView = [mapView dequeueReusableAnnotationViewWithIdentifier:ID]; // 2.缓存池没有可循环利用的大头针view if (annoView == nil) { // 这里应该用MKPinAnnotationView这个子类,一个在构造annotationView时,必须提供数据源模型annotation annoView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:ID]; } // 3.设置view的大头针信息,提供独一无二的数据源模型 annoView.annotation = annotation; // 4.设置图片 annoView.image = [UIImage imageNamed:annotation.icon]; return annoView; } #pragma mark 点击了大头针 - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view { // 0.如果是系统自带的大头针,则直接返回... if (![view.annotation isKindOfClass:[MyAnnotation class]]) { return; } // 1.调用父类的方法,展示详情控制器,并提供数据源 MyAnnotation *anno = view.annotation; [self showDetail:anno.deal]; // 2.让选中的大头针居中(成为中心点) [mapView setCenterCoordinate:anno.coordinate animated:YES]; // 3.让view周边产生一些阴影效果 view.layer.shadowColor = [UIColor blueColor].CGColor; view.layer.shadowOpacity = 1; view.layer.shadowRadius = 10; } #pragma mark - 监听到定位城市发生改变时,重新刷新webView // 0.监听定位完成的通知 - (void)dataChange { // 1.城市对象 City *city = [MetaDataTool sharedMetaDataTool].currentCity; CLGeocoder *geo = [[CLGeocoder alloc] init]; // 全球搜索 某某城市 [geo geocodeAddressString:city.name completionHandler:^(NSArray *placemarks, NSError *error) { // 定位,解析完毕之后,就可以提供经纬度 CLPlacemark *place = placemarks[0]; // 1.用户位置的(中心点) CLLocationCoordinate2D center = place.location.coordinate; city.position = place.location.coordinate; // 重要,将城市用工具记住,因为发送请求时,还用到了城市 名和 经纬度 [LocationTool sharedLocationTool].locationCity = city; // 2.确定好中心点之后,再确定跨度(范围) // 3.根据中心点和跨度之后,就确定好了区域 MKCoordinateRegion region = MKCoordinateRegionMake(center, kSpan); // 4.让mapView显示到指定的区域 [_mapView setRegion:region animated:YES]; }]; } @end