首页 >IOS频道 >【IOS研究院之应用开发】 > IOS研究院之使用谷歌地图API在IOS设备上定位到自己(七)
2012
07-21

IOS研究院之使用谷歌地图API在IOS设备上定位到自己(七)

         这两天抽时间学习了一下IOS下谷歌地图的API  现在很多APP中都会使用谷歌的地图。 个人觉得开发起来还是非常的便利的。废话不多说啦,赶快进入今天的正题。如下所示 这是MOMO的手机,这个项目我是在iPhone上调试的,这正是我的手机,模拟器上我没有试过,模拟器肯定是能打开谷歌地图的,但是好像不能定位地点。大家仔细看我下面的代码描述,其实很简单 真的很简单。本来今天晚上不像写这篇博文的,只是今天的北京雨下的太大了,困住了我回家的路,既然困在了公司那么当然要学习一下啦哈哈哈哈哈哈哈哈哈~~~

 

IOS研究院之使用谷歌地图API在IOS设备上定位到自己(七) - 雨松MOMO程序研究院 - 1

 

OK下面是代码片段。

创建一个工程,如下图所示,先将CoreLocation.framework 和 MapKit.framework  引入工程中,前者是负责定位的,后者是负责地图的。

 

IOS研究院之使用谷歌地图API在IOS设备上定位到自己(七) - 雨松MOMO程序研究院 - 2

 

AppDelegate.h  入口类,没什么好说的我就不解释了。

 

#import <UIKit/UIKit.h>
#import "MapViewController.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UINavigationController *navController;
@property (strong, nonatomic) UIViewController *viewController;
@end

 

AppDelegate.m

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize navController;
@synthesize viewController;

- (void)dealloc
{
    [_window release];
    [super dealloc];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    self.window.backgroundColor = [UIColor whiteColor];
    self.viewController =  [[MapViewController alloc]init];
    self.navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
    [self.window addSubview:navController.view];

    [self.window makeKeyAndVisible];
    return YES;
}

@end

 

主要的东东都写在MapViewController中,请大家仔细看这里。

MapViewController.h

#import <UIKit/UIKit.h>
#import <MapKit/MKReverseGeocoder.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>

@interface MapViewController : UIViewController<CLLocationManagerDelegate,MKMapViewDelegate>
{

   //地图视图, 谷歌地图将加载在这个视图中喔
   MKMapView *myMapView ;
   //地图定位管理器
   CLLocationManager *_locManager ;
}

@end

 

MapViewController.m 注意看这个类噢。

#import "MapViewController.h"

@implementation MapViewController

- (void)dealloc
{
    [_locManager release];
    [super dealloc];
}

- (void)viewDidLoad
{

    [super viewDidLoad];

     self.navigationItem.title  = @"雨松MOMO";  

   	myMapView = [[[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)] autorelease];
	myMapView.delegate = self;
    //在这里先让地图视图隐藏起来,
    //等获取当前经纬度完成后在把整个地图显示出来
    myMapView.hidden = true;
    [self.view addSubview:myMapView];

    //创建定位管理器,
    _locManager = [[CLLocationManager alloc] init];
    [_locManager setDelegate:self];
    [_locManager setDesiredAccuracy:kCLLocationAccuracyBest];   

}

-(void) viewWillAppear:(BOOL)animated
{

    [super viewWillAppear:animated];

    //开始使用手机定位,这是一个回调方法,
    //一旦定位完成后程序将进入
    //- (void)locationManager:(CLLocationManager *)manager
    //didUpdateToLocation:(CLLocation *)newLocation
    //fromLocation:(CLLocation *)oldLocation
    //方法中

    [_locManager startUpdatingLocation];

}

//定位成功后将进入此方法
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{

    //得到当前定位后的经纬度,当前经纬度是有一定偏移量的,
    //使用另一种方法可以很好的解决这个问题
    CLLocationCoordinate2D loc = [newLocation coordinate];
    float lat =  loc.latitude;
    float lon = loc.longitude;

    //让MapView使用定位功能。
    myMapView.showsUserLocation =YES;

    //更新地址,
    [manager stopUpdatingLocation]; 

    //设置定位后的自定义图标。
    MKCircle* circle = [MKCircle circleWithCenterCoordinate:CLLocationCoordinate2DMake(myMapView.userLocation.location.coordinate.latitude, myMapView.userLocation.location.coordinate.longitude) radius:5000];

    //一定要使用addAnnotation 方法把MKCircle加入进视图,
    // 否则下面刷新图标的方法是永远不会进入的 - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
    //切记!!!!
    [myMapView addAnnotation:circle];

     //我们需要通过当前用户的经纬度换成出它现在在地图中的地名
     CLGeocoder *geocoder = [[[CLGeocoder alloc] init] autorelease];
    [geocoder reverseGeocodeLocation: _locManager.location completionHandler:
     ^(NSArray *placemarks, NSError *error) {

         //得到自己当前最近的地名
         CLPlacemark *placemark = [placemarks objectAtIndex:0];

         NSString *locatedAt = [[placemark.addressDictionary valueForKey:@"FormattedAddressLines"] componentsJoinedByString:@", "];

         //locatedAt就是当前我所在的街道名称
         //上图中的中国北京市朝阳区慧中北路
         [myMapView.userLocation setTitle:locatedAt];
         [myMapView.userLocation setSubtitle:@"雨松MOMO在这里噢"]; 

         //这里是设置地图的缩放,如果不设置缩放地图就非常的尴尬,
         //只能光秃秃的显示中国的大地图,但是我们需要更加精确到当前所在的街道,
         //那么就需要设置地图的缩放。
         MKCoordinateRegion theRegion = { {0.0, 0.0 }, { 0.0, 0.0 } };
         theRegion.center= myMapView.userLocation.location.coordinate;

         //缩放的精度。数值越小约精准
         theRegion.span.longitudeDelta = 0.01f;
         theRegion.span.latitudeDelta = 0.01f;
         //让MapView显示缩放后的地图。
         [myMapView setRegion:theRegion animated:YES]; 

         //最后让MapView整体显示, 因为截至到这里,我们已经拿到用户的经纬度,
         //并且已经换算出用户当前所在街道的名称。
         myMapView.hidden = false;
     }];

}

//定位失败后将进入此方法
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {  

    if ( [error code] == kCLErrorDenied )
    {  

        //第一次安装含有定位功能的软件时
        //程序将自定提示用户是否让当前App打开定位功能,
        //如果这里选择不打开定位功能,
        //再次调用定位的方法将会失败,并且进到这里。
        //除非用户在设置页面中重新对该软件打开定位服务,
        //否则程序将一直进到这里。
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"定位服务已经关闭"
                                                        message:@"请您在设置页面中打开本软件的定位服务"
                                                       delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
        [alert release];
        [manager stopUpdatingHeading];
    }
    else if ([error code] == kCLErrorHeadingFailure)
    {  

    }
}  

//在这里我们设置自定义图标来 标志当前我在地图的地方
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
{
    static NSString *identifier = @"com.xys.momo";

    MKAnnotationView *pin = [ mapView dequeueReusableAnnotationViewWithIdentifier:identifier ];
    if ( !pin )
    {

            pin = [ [ MKAnnotationView alloc ] initWithAnnotation:annotation reuseIdentifier:identifier ];
            //随便加载了一张ICON
            //我的icon的大小是48X48 大家可根据仔细的喜好制定自己的icon
            pin.image = [ UIImage imageNamed:@"0.jpg" ];

            //在图中我们可以看到图标的上方,有个气泡弹窗里面写着当前用户的位置所在地
            //原因是这里需要设置了True
            pin.canShowCallout=YES;
            //上图气泡的右侧还有一个带箭头的小按钮
            //这个按钮就是在这里创建的,不过MOMO目前没有写按钮的响应事件喔。
            //细心的朋友可以自己加上。
            UIButton *btn = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
            pin.rightCalloutAccessoryView=btn;
    }

    pin.annotation = annotation;

    return pin;

}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

 

 

最后是本文的源码下载:http://vdisk.weibo.com/s/acdN7

雨松MOMO祝大家学习愉快、工作愉快、生活愉快、互相学习与进步,加油~  话说北京这会应该不下雨了吧??雨停了回家睡觉。 嚯嚯!

———————————-华丽的分割线——————————–

以上方法我在IOS6中使用发现了一点小问题,IOS6使用CLLocationManager定位的时候发现有时候定位到的经纬度是0.0000 所以地图界面中就是一个白屏。那么我将解决的办法贴出来。

//定位成功后将进入此方法
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{

        myMapView.showsUserLocation =YES;

}

 

用这个方法来接受当前地图经纬度信息

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{

    //更新地址,
    [_locManager stopUpdatingLocation];

    //设置定位后的自定义图标。
    MKCircle* circle = [MKCircle circleWithCenterCoordinate:CLLocationCoordinate2DMake(myMapView.userLocation.location.coordinate.latitude, myMapView.userLocation.location.coordinate.longitude) radius:5000];

    [myMapView addAnnotation:circle];

    NSLog(@"%f",myMapView.userLocation.location.coordinate.latitude);

    //我们需要通过当前用户的经纬度换成出它现在在地图中的地名
    CLGeocoder *geocoder = [[[CLGeocoder alloc] init] autorelease];
    [geocoder reverseGeocodeLocation: _locManager.location completionHandler:
     ^(NSArray *placemarks, NSError *error) {

         //得到自己当前最近的地名
         CLPlacemark *placemark = [placemarks objectAtIndex:0];

         NSString *locatedAt = [[placemark.addressDictionary valueForKey:@"FormattedAddressLines"] componentsJoinedByString:@", "];

         //locatedAt就是当前我所在的街道名称
         //上图中的中国北京市朝阳区慧中北路
         [myMapView.userLocation setTitle:locatedAt];
         [myMapView.userLocation setSubtitle:@"你在这里噢"];

         nowLatitude = myMapView.userLocation.location.coordinate.latitude;
         nowLongitude = myMapView.userLocation.location.coordinate.longitude;

         //这里是设置地图的缩放,如果不设置缩放地图就非常的尴尬,
         //只能光秃秃的显示中国的大地图,但是我们需要更加精确到当前所在的街道,
         //那么就需要设置地图的缩放。
         MKCoordinateRegion theRegion = { {0.0, 0.0 }, { 0.0, 0.0 } };
         theRegion.center= myMapView.userLocation.location.coordinate;

         //theRegion.center.latitude = targetLatitude;
         //theRegion.center.longitude = argetLongitude;

         //缩放的精度。数值越小约精准
         theRegion.span.longitudeDelta = 0.01f;
         theRegion.span.latitudeDelta = 0.01f;
         //让MapView显示缩放后的地图。
         [myMapView setRegion:theRegion animated:YES];

         //最后让MapView整体显示, 因为截至到这里,我们已经拿到用户的经纬度,
         //并且已经换算出用户当前所在街道的名称。
         //myMapView.hidden = false;
     }];

}

 

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

IOS研究院之使用谷歌地图API在IOS设备上定位到自己(七)》有 25 条评论

  1. Liumotor说:

    源码地址没了啊,可以再提供一份吗

  2. 祖玉说:

    能出个u3d 读取百度地图sdk android的示列吗?

  3. 楼主,国内谷歌被封了,你是怎么访问到地图的?如果地图可以用,为什么我的就不能显示呢?求解决方案,谢谢

  4. kk说:

    在unity上怎么调用google map 的API啊?

  5. andychen说:

    : CGBitmapContextCreate: unsupported parameter combination: 5 integer bits/component; 16 bits/pixel; 3-component color space; kCGImageAlphaNoneSkipLast; 512 bytes/row. 报这个错是什么原因,大侠。

  6. 贺笛说:

    问一下这个定位的只能在实体手机上测试?

  7. 好厉害,什么都懂,MOMO,我心中的大神,,,,,请回答我今天问你的问题先把,拜托晒!

  8. ╰☆叛逆の王说:

    请问 地图先隐藏等userlocation位置出现后再显示,中间大概有几秒钟白屏现象,你是怎么解决的?

  9. 韩张说:

    请教一下,我使用你的demo定位,位置是对的,但是地址是有偏移的,是什么原因,有方法解决么?

  10. FE_biyr说:

    请教一下MOMO,这个程序用的是google的api吗?mapKit里面有google地图是吗?

  11. 源码下载在真机上运行,有两个图标(把地图缩放到最小),有一个在非洲位置。 MKCircle* circle = [MKCircle circleWithCenterCoordinate:CLLocationCoordinate2DMake(myMapView.userLocation.location.coordinate.latitude, myMapView.userLocation.location.coordinate.longitude) radius:5000];这里的问题。我是新手不知道什么原因,只知道注释掉就不会有上面的情况。CLLocationCoordinate2D loc = [newLocation coordinate]; float lat = loc.latitude; float lon = loc.longitude;这里没有用到…

  12. MOMO,IOS里面提供的Googl地图跟安卓里面的缩放级别是一样的吗?

  13. 曾志军说:

    正在学习,谢谢你的文章。写的很好,以后多向你请教

  14. ST-QK说:

    如果直接用谷歌地图的api的话,怎么感觉跟之前ios5不一样了,调用的方式什么的,请问您还有一些资料么

  15. 刀锋说:

    Google Map 不是收费吗

留下一个回复

你的email不会被公开。 必填项已用 * 标注。