iPhone开发:地图框架入门(一)

原文地址:http://www.highoncoding.com/Articles/804_Introduction_to_MapKit_Framework_for_iPhone_Development.aspx


地图对我们的生活来说是非常重要的一部分。我们经常用地图来确定位置和方向。这篇文章主要是用来介绍地图框架在ios里面的应用。


关键的概念:


MKMapView:用来在ios设备上显示地图的 UI 控件。

Annotation:用来在地图上展示的点,包括了很多的信息,比如坐标,标题,副标题等。

AnnotationView:定义点的视图部分,由 MKAnnotationView 这个类来定义。


1.参考的框架:

   

    在下面的内容里面,我们将用到MapKit.framework 和 CoreLocation.framework 这个两个框架。在开始项目之前,把这两个框架添加到我们的项目里面。如图所示:




2.通过MKMapView这个UI来展示地图:

     在添加这两个框架以后,我们准备开始创建我们的地图套件的应用。

     第一步,在XB里面创建项目,拖动MKMapView这个UI。

     The MapKitDemoAppDelegate.h 实现如下: 

01 #import <UIKit/UIKit.h>
02 #import <MapKit/MapKit.h>
03 #import <CoreLocation/CoreLocation.h>
04 #import "MapPoint.h"
05 #import "LameAnnotationView.h"
06
07 @interface MapKitDemoAppDelegate : NSObject <UIApplicationDelegate,CLLocationManagerDelegate,MKMapViewDelegate,UITextFieldDelegate> {
08
09     CLLocationManager *locationManager;
10     IBOutlet MKMapView *mapView;
11      
12 }
13
14 @property (nonatomic, retain) IBOutlet UIWindow *window;
15 @property (nonatomic,retain) IBOutlet MKMapView *mapView;
16
17 @end

      点击Run,我们可以在仿真器上看到这样的结果:


di er bu



第二步:确定当前的位置:

 在 MapKitDemoAppDelegate.m里面添加下面的代码:

01 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
02 {
03     self.mapView.delegate = self;     
04          
05     locationManager = [[CLLocationManager alloc] init];
06     [locationManager setDelegate:self];
07      
08     [locationManager setDistanceFilter:kCLDistanceFilterNone];
09     [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
10      
11     [self.mapView setShowsUserLocation:YES];
12
13      
14     // Override point for customization after application launch.
15     [self.window makeKeyAndVisible];
16     return YES;
17 }

CLLocationManage是用来获得用户当前位置的类,下面这行代码使得mapview获得用户当前的位置:
1 [self.mapView setShowsUserLocation:YES];


 点击Run,我们可以在仿真器上看到这样的结果:





现在我们能看到用户在地图上被定位,但是现在只是看见了这一个点,我们需要放大这个区域,获得更加具体的信息。通过下面的代码,能够实现这个功能。

在 MapKitDemoAppDelegate.m里面添加下面的代码:



1 - (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views
2 {    
3     MKAnnotationView *annotationView = [views objectAtIndex:0];
4     id<MKAnnotation> mp = [annotationView annotation];
5     MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([mp coordinate] ,250,250);
6      
7     [mv setRegion:region animated:YES];
8 }

上面的函数,是MKMapViewDelegate的一种代理的方法,它的功能是发送事件给当前的控制类,但是,我们必须在函数didFinishLaunchingWithOptions method:里面添加下面的代码:


1 self.mapView.delegate = self;   

我们现在能在地图上看到一个点,MKCoordinateRegion创建了一个初始的区域在地图上,我们可以通过放大和缩小查看这个区域。





仿真器上定位的位置是,苹果公司在美国的位置。你必须在真机上调试才能看到我们当前的位置。


第三步:在地图上添加点:


继承 MKAnnotation这个类,我们创建一个叫做MapPoint的新类。实现如下:

01 #import <Foundation/Foundation.h>
02 #import <CoreLocation/CoreLocation.h>
03 #import <MapKit/MapKit.h>
04
05 @interface MapPoint : NSObject<MKAnnotation> {
06      
07     NSString *title;
08     NSString *subTitle;
09     CLLocationCoordinate2D coordinate;
10      
11 }
12
13 @property (nonatomic,readonly) CLLocationCoordinate2D coordinate;
14 @property (nonatomic,copy) NSString *title;
15 @property (nonatomic,copy) NSString *subTitle;
16
17 -(id) initWithCoordinate:(CLLocationCoordinate2D) c title:(NSString *) t subTitle:(NSString *) st;
18
19 @end

当地图获得新的位置时, MKMapViewDelegate的方法didUpdateUserLocation会被调用。在这个方法里,我们初始化点,并且把他们添加到地图上。

01 - (void)mapView:(MKMapView *)mv didUpdateUserLocation:(MKUserLocation *)userLocation
02 {
03     CLLocationCoordinate2D userCoordinate = userLocation.location.coordinate;
04      
05     for(int i = 1; i<=5;i++)
06     {
07         CGFloat latDelta = rand()*.035/RAND_MAX -.02;
08         CGFloat longDelta = rand()*.03/RAND_MAX -.015;
09          
10         CLLocationCoordinate2D newCoord = { userCoordinate.latitude + latDelta, userCoordinate.longitude + longDelta };
11         MapPoint *mp = [[MapPoint alloc] initWithCoordinate:newCoord title:[NSString stringWithFormat:@"Azam Home %d",i] subTitle:@"Home Sweet Home"];    
12         [mv addAnnotation:mp];
13         [mp release];
14          
15     }
16 }
添加随机的点的坐标,效果如下:





如果想要实现callout的功能,比如弹出来的默认的文本框。我们想做的更加的有趣,在callout的左边或者右边添加一个小房子的图片。


第四步:实现默认点的图层:


The leftCalloutAccessoryView and rightCalloutAccessoryView这两个属性用来展示点的默认的属性。下面代码,展示了一张图片是如何在callout里面被显示出来的:

01 - (MKAnnotationView *)mapView:(MKMapView *)mv viewForAnnotation:(id <MKAnnotation>)annotation
02 {
03     if([annotation isKindOfClass:[MKUserLocation class]])
04     return nil;
05      
06     NSString *annotationIdentifier = @"PinViewAnnotation";
07      
08     MKPinAnnotationView *pinView = (MKPinAnnotationView *) [mapView
09                                                             dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];
10
11      
12     if (!pinView)
13     {
14         pinView = [[[MKPinAnnotationView alloc]
15                     initWithAnnotation:annotation
16                     reuseIdentifier:annotationIdentifier] autorelease];
17          
18         [pinView setPinColor:MKPinAnnotationColorGreen];
19         pinView.animatesDrop = YES;
20         pinView.canShowCallout = YES;
21          
22         UIImageView *houseIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"house.png"]];
23         pinView.leftCalloutAccessoryView = houseIconView;
24         [houseIconView release];        
25     }
26     else
27     {
28         pinView.annotation = annotation;
29     }
30
31     return pinView;
32
33 }

为了提升地图的表现效果,我们用id来保存地图的点的类型。也就是说,同一种点,用在地图的不同部分,重复利用同一种点,而不在重新的创建它。run 代码,在仿真器上点击绿的点,能够看到以下的结果:



上面的显示中,一张图片在点的callout里面显示出来了,但是图片的尺寸太大了。我们可以通过下面的代码调整图片大小:


1 UIImageView *houseIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"house.png"]];
2         [houseIconView setFrame:CGRectMake(0, 0, 30, 30)];
3         pinView.leftCalloutAccessoryView = houseIconView;
4         [houseIconView release];        


    尽管我们初始化了点的LameAnnotationViewcallout,我们没有改变点的样子,它是默认的样子。点能够被改变,通过建立一个点的类,重载DrawRect这个方法。继承,我们重新创建一个类,LameAnnotationView。以下是实现的代码:


01 #import "LameAnnotationView.h"
02
03 @implementation LameAnnotationView
04
05 - (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
06 {
07     self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
08     if (self != nil)
09     {
10         CGRect frame = self.frame;
11         frame.size = CGSizeMake(60.0, 85.0);
12         self.frame = frame;
13         self.backgroundColor = [UIColor clearColor];
14         self.centerOffset = CGPointMake(-5, -5);
15     }
16     return self;
17 }
18
19 -(void) drawRect:(CGRect)rect
20 {
21     [[UIImage imageNamed:@"house.png"] drawInRect:CGRectMake(30, 30.0, 30.0, 30.0)];
22 }
23
24 @end

为了使用我们创建的新点的类,用LameAnnotationView来替代默认的类,代码如下:


01 - (MKAnnotationView *)mapView:(MKMapView *)mv viewForAnnotation:(id <MKAnnotation>)annotation
02 {
03     if([annotation isKindOfClass:[MKUserLocation class]])
04     return nil;
05      
06     NSString *annotationIdentifier = @"PinViewAnnotation";
07      
08     LameAnnotationView *pinView = (LameAnnotationView *) [mapView
09                                                             dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];
10
11      
12     if (!pinView)
13     {
14         pinView = [[[LameAnnotationView alloc]
15                     initWithAnnotation:annotation
16                     reuseIdentifier:annotationIdentifier] autorelease];
17          
18 //[pinView setPinColor:MKPinAnnotationColorGreen];
19        // pinView.animatesDrop = YES;
20         pinView.canShowCallout = YES;
21          
22         UIImageView *houseIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"house.png"]];
23         [houseIconView setFrame:CGRectMake(0, 0, 30, 30)];
24         pinView.leftCalloutAccessoryView = houseIconView;
25         [houseIconView release];        
26     }
27     else
28     {
29         pinView.annotation = annotation;
30     }
31
32     return pinView;
33
34 }





我们在初始化点的视图时候,我们忽略了产生点的时候的特效。但是,这个部分的内容,可以通过特效的库,添加进来。以下代码是用来显示点被添加的时候,的效果。


01 - (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views
02 {
03      
04     // add the animation here
05      
06     CGRect visibleRect = [mapView annotationVisibleRect];
07      
08     for(MKAnnotationView *view in views)
09     {
10         if([view isKindOfClass:[LameAnnotationView class]])
11         {
12             CGRect endFrame = view.frame;
13              
14             CGRect startFrame = endFrame;
15          
16             startFrame.origin.y = visibleRect.origin.y - startFrame.size.height;
17             view.frame = startFrame;
18            
19              
20             [UIView beginAnimations:@"drop" context:NULL];
21             [UIView setAnimationDuration:2];
22              
23              
24             view.frame = endFrame;
25             [UIView commitAnimations];
26         }
27     }
28       
29      
30     MKAnnotationView *annotationView = [views objectAtIndex:0];
31     id<MKAnnotation> mp = [annotationView annotation];
32     MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([mp coordinate] ,5000,5000);
33      
34     [mv setRegion:region animated:YES];
35 }

现在点击run,我们可以看到house点从天而降的下过,这个方法我们在  didAddAnnotationViews  方法里面实现过。


结论: 

在这篇文章里面,我们学会了如何使用MapKit。同时,我们还证明了,如何去初始化点,初始化点的视图,特别是视图的显示效果,它能够增加用户的体验。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值