Core Location和MapKit的一些简单使用

Core Location

1. 基本对象是CLLocation,有属性coordinate, altitude, horizontal/vertical Accuracy, timestamp, speed, course

typedef {
CLLocationDegrees latitude; // a double
CLLocationDegrees longitude; // a double 
} CLLocationCoordinate2D;    // 经纬度

@property (readonly) CLLocationAccuracy horizontalAccuracy; // in meters 
@property (readonly) CLLocationAccuracy verticalAccuracy;

kCLLocationAccuracyBestForNavigation;
kCLLocationAccuracyBest;
kCLLocationAccuracyNearestTenMeters;
kCLLocationAccuracyHundredMeters;
kCLLocationAccuracyKilometer;
kCLLocationAccuracyThreeKilometers;


- (CLLocationDistance)distanceFromLocation:(CLLocation *)otherLocation; // in meters 两个位置之间的距离


2. 总是通过CLLocationManager来获取CLLocation(通过其代理),其一般的使用方法为:

(1)检查硬件是否支持你需要的位置更新

(2)创建一个CLLocationManager实例,并设置接收更新的代理对象

(3)根据你的需求对CLLocationManager进行配置

(4)启动CLLocationManager来监视改变。


3. Core Location Manager的一些设置

@property CLLocationAccuracy desiredAccuracy; // always set this as low as possible 
@property CLLocationDistance distanceFilter; 

- (void)startUpdatingLocation;
- (void)stopUpdatingLocation;

- (void)startMonitoringSignificantLocationChanges;
- (void)stopMonitoringSignificantLocationChanges;


Core Location框架提供了三种用于追踪设备当前位置的服务

  • The significant-change location 

    service 提供了低耗电的方法来获取当前位置,当前位置改变时会发出通知
  • The standard location service 提供了一种可设置的方法来获取当前位置

  • Region monitoring 监视特定地区的跨越

Listing 1  Starting the standard location service
- (void)startStandardUpdates
{
    // 创建location manager
    if (nil == locationManager)
        locationManager = [[CLLocationManager alloc] init];
 
    locationManager.delegate = self;

  // 设置获取位置的精确度,越精确越耗电
    locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
 
    // 设置距离过滤器,超过次距离就更新一次位置
    locationManager.distanceFilter = 500;
 
    [locationManager startUpdatingLocation];
}

Listing 2 Significant-Change Location Service

- (void)startSignificantChangeUpdates
{
    // Create the location manager if this object does not
    // already have one.
    if (nil == locationManager)
        locationManager = [[CLLocationManager alloc] init];
 
    locationManager.delegate = self;
    [locationManager startMonitoringSignificantLocationChanges];
}

4. 检查硬件

+ (BOOL)locationServicesEnabled; // has the user enabled location monitoring in Settings? 
+ (BOOL)headingAvailable; // can this hardware provide heading info (compass)? 
+ (BOOL)significantLocationChangeMonitoringAvailable; // only if device has cellular?
+ (BOOL)regionMonitoringAvailable; // only certain iOS4 devices
+ (BOOL)regionMonitoringEnabled; // by the user in Settings

当程序初次使用位置服务时,会询问用户。可以提供一个string来描述使用目的。如果用户拒绝,则上面所有方法均返回NO

 @property (copy) NSString *purpose


5. 获取位置更新

// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
    fromLocation:(CLLocation *)oldLocation
{
    // If it's a relatively recent event, turn off updates to save power
    NSDate* eventDate = newLocation.timestamp;
    NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
    if (abs(howRecent) < 15.0)
    {
        NSLog(@"latitude %+.6f, longitude %+.6f\n",
                newLocation.coordinate.latitude,
                newLocation.coordinate.longitude);
    }
    // else skip the event and process the next one.
}

- (void)locationManager:(CLLocationManager *)manager
       didFailWithError:(NSError *)error;

typedef enum {
   kCLErrorLocationUnknown  = 0,
   kCLErrorDenied,                           // 如果用户拒绝开启位置服务,那么应该停止location manager
   kCLErrorNetwork,
   kCLErrorHeadingFailure,
   kCLErrorRegionMonitoringDenied,
   kCLErrorRegionMonitoringFailure,
   kCLErrorRegionMonitoringSetupDelayed,
} CLError;


6. Geocoding Location Data

Geocoder对象使用网络服务来将经纬度转换为具体地址信息,iOS当前只支持经纬度转地址信息,不能将位置信息转换为经纬度

创建一个MKReverseGeocoder实例,设置代理,调用start方法。
代理会接受到 reverseGeocoder:didFindPlacemark:和reverseGeocoder:didFailWithError:


@implementation MyGeocoderViewController (CustomGeocodingAdditions)  
- (void)geocodeLocation:(CLLocation*)location forAnnotation:(MapLocation*)annotation  
{  
    MKReverseGeocoder* theGeocoder = [[MKReverseGeocoder alloc] initWithCoordinate:location.coordinate];  
   
    theGeocoder.delegate = self;  
    [theGeocoder start];  
}  
   
// Delegate methods  
- (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFindPlacemark:(MKPlacemark*)place  
{  
    MapLocation*    theAnnotation = [map annotationForCoordinate:place.coordinate];  
    if (!theAnnotation)  
        return;  
   
   // Associate the placemark with the annotation.  
    theAnnotation.placemark = place;  
   
    // Add a More Info button to the annotation's view.  
    MKPinAnnotationView*  view = (MKPinAnnotationView*)[map viewForAnnotation:annotation];  
    if (view && (view.rightCalloutAccessoryView == nil))  
    {  
        view.canShowCallout = YES;  
        view.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];  
    }  
}  
   
- (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFailWithError:(NSError*)error  
{  
    NSLog(@"Could not retrieve the specified place information.\n");  
}  
@end  
   
@implementation MKMapView (GeocoderAdditions)  
   
- (MapLocation*)annotationForCoordinate:(CLLocationCoordinate2D)coord  
{  
    // Iterate through the map view's list of coordinates  
    // and return the first one whose coordinate matches  
    // the specified value exactly.  
    id<MKAnnotation> theObj = nil;  
   
    for (id obj in [self annotations])  
    {  
        if (([obj isKindOfClass:[MapLocation class]]))  
        {  
            MapLocation* anObj = (MapLocation*)obj;  
   
            if ((anObj.coordinate.latitude == coord.latitude) &&  
                (anObj.coordinate.longitude == coord.longitude))  
            {  
                theObj = anObj;  
                break;  
            }  
        }  
    }  
  
    return theObj;  
}  
@end



MapKit

1. MKMapView 显示地图

2. 地图上可以显示注释(annotation),每个annotation由coordinate,title,subtitle构成,并由MKAnnotationView来显示

3. Annotation可以有一个callout,当annotation view被点击时显示,默认情况下只是显示title和subtitle,不过你可以添加左右accessory views

4. MKMapView显示一个遵守MKAnnotation协议的数组对象

@property (readonly) NSArray *annotations; // contains id <MKAnnotation> objects
MKAnnotation protocol
@protocol MKAnnotation <NSObject>
@property (readonly) CLLocationCoordinate2D coordinate;
@optional
@property (readonly) NSString *title;
@property (readonly) NSString *subtitle;
@end
typedef {
    CLLocationDegrees latitude;
    CLLocationDegrees longitude;
} CLLocationCoordinate2D;




5. 管理map view的annotations的方法

- (void)addAnnotation:(id <MKAnnotation>)annotation;
- (void)addAnnotations:(NSArray *)annotations;
- (void)removeAnnotation:(id <MKAnnotation>)annotation;
- (void)removeAnnotations:(NSArray *)annotations;

6. MKMapView使用跟TableView类似的方法来重用annotation view

7. Annotations通过MKAnnotationView的子类显示在地图上,默认为MKPinAnnotationView

8. 如果MKAnnotationView的canShowCallout设置为YES,那么点击会显示,同时会调用

- (void)mapView:(MKMapView *)sender didSelectAnnotationView:(MKAnnotationView *)aView;
//This is a great place to set up the MKAnnotationView‘s callout accessory views lazily.

9. MKAnnotationViews的创建方法跟tableviewcell在tableview中的创建类似

- (MKAnnotationView *)mapView:(MKMapView *)sender
            viewForAnnotation:(id <MKAnnotation>)annotation
{
    MKAnnotationView *aView = [sender dequeueReusableAnnotationViewWithIdentifier:IDENT];
    if (!aView) {
        aView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
                                                reuseIdentifier:IDENT];
        // set canShowCallout to YES and build aView’s callout accessory views here 
             }
    aView.annotation = annotation; // yes, this happens twice if no dequeue
    // maybe load up accessory views here (if not too expensive)?
    // or reset them and wait until mapView:didSelectAnnotationView: to load actual data
    return aView;
}

10. MKAnnotationView的一些属性

@property id <MKAnnotation> annotation; // the annotation; treat as if readonly 
@property UIImage *image; // instead of the pin, for example
@property UIView *leftCalloutAccessoryView; // maybe a UIImageView
@property UIView *rightCalloutAccessoryView; // maybe a “disclosure” UIButton 
@property BOOL enabled; // NO means it ignores touch events, no delegate method, no callout 
@property CGPoint centerOffset; // where the “head of the pin” is relative to the image 
@property BOOL draggable; // only works if the annotation implements setCoordinate:

11. 如果你设置一个callout accessory view为一个UIControl

e.g. aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 
The following MKMapViewDelegate method will get called when the accessory view is touched ...

- (void)mapView:(MKMapView *)sender 
        annotationView:(MKAnnotationView *)aView
        calloutAccessoryControlTapped:(UIControl *)control;

12. 使用一下代理方法来加载accessory views

-(void)mapView:(MKMapView *)sender didSelectAnnotationView:(MKAnnotationView *)aView 
{
   if ([aView.leftCalloutAccessoryView isKindOfClass:[UIImageView class]]) {
          UIImageView *imageView = (UIImageView *)aView.leftCalloutAccessoryView; 
          imageView.image = ...; // if you do this in a GCD queue, be careful, views are reused!
   }
}

13. 地图类型

@property MKMapType mapType;
enum {  
    MKMapTypeStandard = 0,  
    MKMapTypeSatellite,  
    MKMapTypeHybrid  
};  
typedef NSUInteger MKMapType;  



14. 显示用户当前地址

@property BOOL showsUserLocation;
@property (readonly) BOOL isUserLocationVisible;
@property (readonly) MKUserLocation *userLocation;
MKUserLocation is an object which conforms to MKAnnotation which holds the user’s location.

15.限制用户对地图的操作

@property BOOL zoomEnabled;
@property BOOL scrollEnabled;

16. 控制地图的显示区域

@property MKCoordinateRegion region;
typedef struct {
    CLLocationCoordinate2D center;
    MKCoordinateSpan span;
} MKCoordinateRegion;

typedef struct {
    CLLocationDegrees latitudeDelta;
    CLLocationDegrees longitudeDelta;
}
- (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated; // animate
注意:
你赋给region属性的值通常不是最终保存的值,在设置显示区域的时候同时也设置了缩放等级。map view不能显示任意的缩放等级,因此map view会选择一个能够尽可能显示你指定区域大小的缩放等级,然后根据此时显示的区域来保存。

@property CLLocationCoordinate2D centerCoordinate;
- (void)setCenterCoordinate:(CLLocationCoordinate2D)center animated:(BOOL)animated;

17. 地图载入通知

Remember that the maps are downloaded from Google earth.
- (void)mapViewWillStartLoadingMap:(MKMapView *)sender;
- (void)mapViewDidFinishLoadingMap:(MKMapView *)sender;
- (void)mapViewDidFailLoadingMap:(MKMapView *)sender withError:(NSError *)error;

18.








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值