iOS_21團購_地圖功能 – iPhone手機開發技術文章 iPhone軟體開發教學課程

最終效果圖:

vcD4KPHA+09LPwr3HtcS72LW908O7p8671sOwtMWlOjwvcD4KPHA+PGltZyBzcmM9″/uploadfile/Collfiles/20140826/2014082608540575.png” alt=”\”>

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 
#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 ()
{
    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

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *