浅谈iOS开发过程中的Core Location &Map Kit
两个月前,抱着对iOS开发的兴趣开始接触苹果设备的开发,开始接触object -C,以后用OC来代替,本人新人一枚,以后会经常写一些东西给大家分享,有做的不到位的,请大家多多包涵。今天是我发表的第一篇博客。有什么错误的或者是写的不到位的情况。请大家指正,大家共同进步。今天呢我来介绍一些关于iOS开发过程中的地图类。
OC是面向对象的语言,和我们接触的C++,JAVA是一样的。在OC中除了基本的数据类型外,其他的基本上是通过对象来调用的。言归正传,iOS开发过程中,添加地图首先用到的主要的类和数据结构有:MKMapView是用来显示地图的视图,CLLocationCoordinate2D是用来表示一个地区的地理坐标,在CLLocationCoordinate2D中需要注意的是 :东经和北纬表示是正坐标。MKCoordinateRegion 是用来表示地图的显示区域,它的定义是
typedefstruct {
CLLocationCoordinate2D center;//用来表示位置的中心坐标
MKCoordinateSpan span;//水平和垂直显示地图的大小,也定义了地图的zoom级别
} MKCoordinateRegion;
MKMapView 中有很多属性可以设置 比如:zoomEnabled scrollEnabled showsUserLocation 等方法,可以根据需求设定。更多可以查看苹果的官方文档。
self.mapView =[[MKMapViewalloc] initWithFrame:self.view.bounds];
self.mapView.mapType =MKMapTypeStandard;
self.mapView.zoomEnabled =YES ;
self.mapView.scrollEnabled =YES;
self.mapView.showsUserLocation =NO;
self.mapView.delegate =self;
CLLocationCoordinate2D的初始化有以下几种:
1.CLLocationCoordinate2D
coordinate = { , };
2. CLLocationCoordinate2D coordinate;
coordinate.latitude =34.4668711;
coordinate.longitude =113.453221
// CLLocationCoordinate2D coordinate ={34.4668711,113.453221}; CLLocationCoordinate2D coordinate; coordinate.latitude =34.4668711;
coordinate.longitude =113.453221;
MKCoordinateSpan span = {1,1};//
表示显示区域的精度,值越小表示的范围越精确,值越大表示的范围越大,但是不精确
下面是根据地理坐标和span创建表示区域的值
MKCoordinateRegion的初始化方法也有如下几种
1. MKCoordinateRegion region = {coordinate,span}; //初始化方法
2. MKCoordinateRegion region;
region = {coordinate,span};
region = MKCoordinateRegionMake(coordinate, span);
3. region = MKCoordinateRegionMakeWithDistance(coordinate, 111*1000*span.latitudeDelta, 111*1000*span.longitudeDelta); 中间传的参数是已经定义好的。
MKCoordinateRegion region ={coordinate,coordinateSpan}; // // MKCoordinateRegion region ; // region =MKCoordinateRegionMake(coordinate, coordinateSpan); // region =MKCoordinateRegionMakeWithDistance(coordinate, coordinateSpan.latitudeDelta, coordinateSpan.longitudeDelta); // // [self.mapView setRegion:region];
CLLocationManager 使用来管理位置信息的。苹果官方给出的文档如下:
The CLLocationManager class defines the interface for configuring the delivery of location- and heading-related events to your application. You use an instance of this class to establish the parameters that determine when location and heading events should be delivered and to start and stop the actual delivery of those events. You can also use a location manager object to retrieve the most recent location and heading data.
self.locationManager =[[CLLocationManager alloc] init]; self.locationManager.delegate =self; self.locationManager.distanceFilter =kCLDistanceFilterNone; self.locationManager.desiredAccuracy =kCLLocationAccuracyBest; [self.locationManager startUpdatingLocation];
有了上述的方法就可以简单的实现一个地图的功能了。
我们再来看看一些使用到的方法,我只是提一些比较常用的并且主要的方法。
在CLLocationManager中获取位置信息的方法
1.- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation //这个方法在6.0以后就取消了
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
// CLLocationDistance distance =[newLocation distanceFromLocation:oldLocation];
// NSLog(@"dis is %f",distance/1000.0);
}
2。- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
这两个方法都可以获取位置信息,但是如果两个方法都写得话 只会执行第二个方法。 所以推荐使用地二个方法。
-(void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
这个方法可以获取程序执行过程中得错误信息,没有的话就位空。
有了上述方法我们就可以创建一个简单的显示地图的程序了。
当然了,地图上面还有一个比较重要的类就是Annotation类,这个类提供地图的注解。那么如何在地图上实现一个Annotation呢
我们来看看annotation。MKAnnotation中有协议和委托(如果没有实现系统会默认生成一个红色大头针的注解图标)
实现注解类的基本步骤有:
*创建注解类(需要声明实现MKAnnotation协议)
*实例化注解类对象
*将实例化的注解类对象添加到MKMapView对象
*类似于UITableViewCell的方法创建MKAnnotationView 对象,这个对象用于最终在地图上面显示。
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
//当在mapView上添加annotation对象的时候,这个方法会被调用,用来设置显示界面;
-(MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { if ([annotation isKindOfClass:[MKUserLocation class]]) { return nil; } static NSString *indetifier =@"Indentifier"; QYCustomView *pinAnnotationView =(QYCustomView *)[mapView dequeueReusableAnnotationViewWithIdentifier:indetifier]; if (nil ==pinAnnotationView) { pinAnnotationView =[[QYCustomView alloc] initWithAnnotation:annotation reuseIdentifier:indetifier]; } pinAnnotationView.canShowCallout =YES; UIImageView *leftImagView =[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)]; leftImagView.image =[UIImage imageNamed:@"Icon 2"]; pinAnnotationView.leftCalloutAccessoryView =leftImagView; UIButton *btn =[UIButton buttonWithType:UIButtonTypeDetailDisclosure]; [btn addTarget:self action:@selector(onButton:) forControlEvents:UIControlEventTouchUpInside]; pinAnnotationView.rightCalloutAccessoryView =btn; return pinAnnotationView; }
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control;//这个方法是当MkAnnotationView 对象被点击的时候调用
当然了,这些方法是代理方法,在开始的时候应该实现它的delegate 。
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control { UIAlertView *alertView =[[UIAlertView alloc] initWithTitle:@"Tapped" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alertView show]; }
下面来介绍实现一个大头针的方法的介绍
MKPointAnnotation *pointAnnotation =[[MKPointAnnotationalloc] init]; pointAnnotation.coordinate =coordinate; pointAnnotation.title =@"河南郑州"; pointAnnotation.subtitle =@"河南青云";
在这里需要注意的是MkpointAnnotation 相当于一个Model ,只是用来提供数据的,如果只是有这个信息是不会显示的,它是依附于MKAnnotationView 的对象的,添加大头针从天而降的方法是添加一个 MKAnnotationView对象 pinAnnotationView pinAnnotationView.animatesDrop =YES;就行了。
下面我们来讲一下位置的反编码,具体的理解应该是知道CLLocation 对象的信息,如何获取具体的国家,省份,省会,街道的具体的信息。具体的反编码要用到CLGeocoder对象,还有一个就是CLPlacemark 类,CLPlacemark反编码后的位置结果,包含位置信息国家,省,区(市),街道,位置名等。
CLGeocoder *geocoder = [[CLGeocoder alloc] init]; CLLocation *location = [[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude]; [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) { if (nil != error) { NSLog(@"error info is %@",error); return
} // CLPlacemark for (CLPlacemark *placeMark in placemarks) {
NSLog(@"%@,%@,%@,%@",placeMark.country,placeMark.administrativeArea,placeMark.locality,placeMark.thoroughfare); }
}];
想要打印什么信息看有什么需求,具体的请查看苹果官方文档。还有中间用到了block块的概念,如果有什么不懂,请参考block块的信息。block块的使用就是代码中以^开头的。
有了上述的信息大家基本上可以完成常用的功能实现,但是现在有位置信息的app,像高德地图,嘀嘀打车等app 显示的内容比较丰富,最后我们就来将一下怎么样自定义自己的视图。
首先自定义一个自己的类继承自 MKAnnotationView,如:QYAnnotationView : MKAnnotationView。然后再这个类中重写
- (void)setSelected:(BOOL)selected这个方法,当然也可以不定义自己的类。
- (void)setSelected:(BOOL)selected {
[super setSelected:selected]; UIView *view = [[UILabel alloc] initWithFrame:CGRectMake(-40, -40, 100, 40)] view.backgroundColor = [UIColororangeColor]; UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; imageView.image = [UIImage imageNamed:@"icon"]; [view addSubview:imageView]; [self addSubview:view]; }
还有一种方法就是重写
- (void)setSelected:(BOOL)selected animated:(BOOL)animated这个方法,产生的效果是一样的,只不过后面的这个添加了一个动画。有兴趣的可以分别写两个看看区别是什么,这里就不在多说了
但是这样就完成了吗 ?大家会发现,当点击图标的时候出现两个重叠的视图,不是自己想要的结果怎么办?
那么如何解决这个问题呢 ,其实很简单 ,就是在在定义MKAnnotationView 的对象上面修改它的canShowCallout = NO;亲测可用,希望能帮到被这个问题困扰的人。