所以这里简单介绍定位与地图。
iOS设备提供三种不同定位途径,
蜂窝式移动电话基站定位;
WiFi定位,通过查询一个WiFi路由器的地理位置信息,比较省电;
GPS卫星定位,通过3~4颗卫星定位,最为准确,但是耗电量大。
iOS系统如果能够接收GPS信息,那么设备优先级是:
GPS > WiFi > 基站
开发人员不能选择哪种定位方式。
定位服务使用CoreLocation框架,主要使用CLLocationMananger、CLLocationManangerDelegate和CLLocation三个类,
这里要注意,CLLocationManangerDelegate 的locationManager:didUpdateToLocation:fromLocation:方法得到的坐标是火星坐标,这个原因你懂得,所以需要转换成真实的地理坐标。
我使用的是一个第三方的CSqlite类,有一个转换坐标的数据库,你调用就可以转换为正确坐标了。
得到经纬度后,要进行地理位置信息反编码,使用CLGeocoder类实现,将地理坐标转换为地理文字描述信息,这些文字描述信息被封装在CLPlacemark类中。
当然给定地理信息的文字描述,也可以进行地理信息编码查询,转换为地理坐标,也是采用CLGeocoder类。
// 在范围内返回1,不在返回0
-(int)mutableBoundConrtolAction:(NSMutableArray *)arrSome:(CLLocationCoordinate2D )myCoordinate4{
int n=arrSome.count;
float vertx[n];
float verty[n];
for (int i=0; i<arrSome.count; i++) {
//MyPoint类存储的是经度和纬度
vertx[i]=((MyPoint *)(arrSome[i])).x;
verty[i]=((MyPoint *)(arrSome[i])).y;
}
if (arrSome.count==0) {
return 1;
}
BOOL i=pnpoly(arrSome.count, vertx, verty, myCoordinate4.latitude, myCoordinate4.longitude);
if (i) {
return 1;
}else{
return 0;
}
return 1;
}
//多边形由边界的坐标点所构成的数组组成,参数格式 该数组的count, 多边形边界点x坐标 的组成的数组,多边形边界点y坐标 的组成的数组,需要判断的点的x坐标,需要判断的点的y坐标
BOOL pnpoly (int nvert, float *vertx, float *verty, float testx, float testy) {
int i, j;
BOOL c=NO;
for (i = 0, j = nvert-1; i < nvert; j = i++) {
if ( ( (verty[i]>testy) != (verty[j]>testy) ) &&
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
c = !c;
}
return c;
}
地图我目前用过系统、百度以及高德,开发人员使用都是差不多的,下面的代码涉及的类都是高德地图api提供的类。
-(void)SetMapRegion:(CLLocationCoordinate2D)myCoordinate
{
MACoordinateRegion theRegion = { {0.0, 0.0 }, { 0.0, 0.0 } };
theRegion.center=myCoordinate;
[self.m_map setScrollEnabled:YES];
theRegion.span.longitudeDelta = 0.01f;
theRegion.span.latitudeDelta = 0.01f;
[self.m_map setRegion:theRegion animated:YES];
}
-(void)panMap:(NSString *)direction{
CLLocationCoordinate2D changeCoordinate=self.m_map.centerCoordinate;
CGPoint changePoint=[self.m_map convertCoordinate:changeCoordinate toPointToView:self.m_map];
if ([direction isEqualToString:@"up"]) {
changePoint.y=changePoint.y+50;
}else if ([direction isEqualToString:@"down"]) {
changePoint.y=changePoint.y-50;
}else if ([direction isEqualToString:@"left"]) {
changePoint.x=changePoint.x-50;
}else if ([direction isEqualToString:@"right"]) {
changePoint.x=changePoint.x+50;
}
changeCoordinate=[self.m_map convertPoint:changePoint toCoordinateFromView:self.m_map];
[self.m_map setCenterCoordinate:changeCoordinate animated:YES];
}
-(void)isAtCurrentRegion:(CLLocationCoordinate2D)coordiante{
CGPoint point=[self.m_map convertCoordinate:coordiante toPointToView:self.view];
if ((point.x<0)||(point.y<0)||(point.x>WScreen)||(point.y>HScreen)) {
// 如果不在 设置该点为地图中心点
[self SetMapRegion:coordiante];
}
}
系统地图使用MapKit框架,核心是MKMapView类,显示地图只要添加MKMapView实例就可以了。
如果要实现在地图上添加标注点,
第一是触发添加动作,
第二实现MKMapViewDelegate的mapView:viewForAnnotation:完成添加标注。
高德地图实现的原理也是一样的,高德地图使用的是MAMapKit框架。
对于annotation,一般会自定义一个继承NSobject并且实现了maannotation协议的类,然后使用mapview的addAnnotation:方法就可以。
MKReverseGeocoder类可以实现coordinate的反编码,这里需要实现它的代理,把得到的地理文字描述信息赋给annotation。
这里需要实现代理的mapView:viewForAnnotation:方法,一个标注其实就是一个MAAnnotationView,标注有点类似tableviewcell,这里也有重用机制。
实现代理的mapView:annotationView:calloutAccessoryControlTapped:方法可以响应leftCalloutAccessoryView或者rightCalloutAccessoryView的点击事件,不过这个accessory view必须继承自UIControl。
MAPolyline类定义一个由多个点相连的多段线,点与点之间尾部想连但第一点与最后一个点不相连, 通常MAPolyline是MAPolylineView的model,它提供了两个方法polylineWithPoints:count:、polylineWithCoordinates:count:用来添加线条,
然后再通过map view的addOverlay:方法把Polyline实例添加进去,
最后实现mapviewdelegate的mapView:viewForOverlay:方法就可以了。
注意如果一开始添加的不是coordinate,而是point,可以通过map view的convertPoint:toCoordinateFromView:方法进行转换。
MAPolygon类定义的就是一个不规则的由多个点组成的闭合多边形,点与点之间按顺序尾部相连, 第一个点与最后一个点相连, 通常MAPolygon是MAPolygonView的model,
首先需要添加坐标点的数组,可以使用polygonWithCoordinates:count:方法或者polygonWithPoints:count:方法,
然后把这个polygon通过addOverlay:方法添加到map view上就可以了。
然后可以在mapviewdelegate里面的mapView:viewForOverlay:方法里面给MAPolygonView的属性赋值,这样一个完整的多边形就出来了。
不管是高德地图还是百度地图等第三方,都会有一个同MapSearchKit,这是一个用于查询的框架,有兴趣的朋友可以多加研究。