Core Location

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


  1. <span style="font-size:18px;">typedef {  
  2. CLLocationDegrees latitude; // a double  
  3. CLLocationDegrees longitude; // a double   
  4. } CLLocationCoordinate2D;    // 经纬度</span>  


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

  3. kCLLocationAccuracyBestForNavigation;  
  4. kCLLocationAccuracyBest;  
  5. kCLLocationAccuracyNearestTenMeters;  
  6. kCLLocationAccuracyHundredMeters;  
  7. kCLLocationAccuracyKilometer;  
  8. kCLLocationAccuracyThreeKilometers;  


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




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

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

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

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

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


3. Core Location Manager的一些设置


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

  3. - (void)startUpdatingLocation;  
  4. - (void)stopUpdatingLocation;  

  5. - (void)startMonitoringSignificantLocationChanges;  
  6. - (void)stopMonitoringSignificantLocationChanges;  




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


  • The significant-change location 
     service 提供了低耗电的方法来获取当前位置,当前位置改变时会发出通知
  • The standard location service 提供了一种可设置的方法来获取当前位置
  • Region monitoring 监视特定地区的跨越



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

  7.     locationManager.delegate = self;  

  8.   // 设置获取位置的精确度,越精确越耗电  
  9.     locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;  

  10.     // 设置距离过滤器,超过次距离就更新一次位置  
  11.     locationManager.distanceFilter = 500;  

  12.     [locationManager startUpdatingLocation];  
  13. }  


  1. Listing 2 Significant-Change Location Service  

  2. - (void)startSignificantChangeUpdates  
  3. {  
  4.     // Create the location manager if this object does not  
  5.     // already have one.  
  6.     if (nil == locationManager)  
  7.         locationManager = [[CLLocationManager alloc] init];  

  8.     locationManager.delegate = self;  
  9.     [locationManager startMonitoringSignificantLocationChanges];  
  10. }  


4. 检查硬件


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



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

 @property (copy) NSString *purpose


5. 获取位置更新


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


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

  3. typedef enum {  
  4.    kCLErrorLocationUnknown  = 0,  
  5.    kCLErrorDenied,                           // 如果用户拒绝开启位置服务,那么应该停止location manager  
  6.    kCLErrorNetwork,  
  7.    kCLErrorHeadingFailure,  
  8.    kCLErrorRegionMonitoringDenied,  
  9.    kCLErrorRegionMonitoringFailure,  
  10.    kCLErrorRegionMonitoringSetupDelayed,  
  11. } CLError;  



6. Geocoding Location Data


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


创建一个MKReverseGeocoder实例,设置代理,调用start方法。

代理会接受到 reverseGeocoder:didFindPlacemark:和reverseGeocoder:didFailWithError: 



  1. @implementation MyGeocoderViewController (CustomGeocodingAdditions)    
  2. - (void)geocodeLocation:(CLLocation*)location forAnnotation:(MapLocation*)annotation    
  3. {    
  4.     MKReverseGeocoder* theGeocoder = [[MKReverseGeocoder alloc] initWithCoordinate:location.coordinate];    

  5.     theGeocoder.delegate = self;    
  6.     [theGeocoder start];    
  7. }    

  8. // Delegate methods    
  9. - (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFindPlacemark:(MKPlacemark*)place    
  10. {    
  11.     MapLocation*    theAnnotation = [map annotationForCoordinate:place.coordinate];    
  12.     if (!theAnnotation)    
  13.         return;    

  14.    // Associate the placemark with the annotation.    
  15.     theAnnotation.placemark = place;    

  16.     // Add a More Info button to the annotation's view.    
  17.     MKPinAnnotationView*  view = (MKPinAnnotationView*)[map viewForAnnotation:annotation];    
  18.     if (view && (view.rightCalloutAccessoryView == nil))    
  19.     {    
  20.         view.canShowCallout = YES;    
  21.         view.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];    
  22.     }    
  23. }    

  24. - (void)reverseGeocoder:(MKReverseGeocoder*)geocoder didFailWithError:(NSError*)error    
  25. {    
  26.     NSLog(@"Could not retrieve the specified place information.\n");    
  27. }    
  28. @end    

  29. @implementation MKMapView (GeocoderAdditions)    

  30. - (MapLocation*)annotationForCoordinate:(CLLocationCoordinate2D)coord    
  31. {    
  32.     // Iterate through the map view's list of coordinates    
  33.     // and return the first one whose coordinate matches    
  34.     // the specified value exactly.    
  35.     id<MKAnnotation> theObj = nil;    

  36.     for (id obj in [self annotations])    
  37.     {    
  38.         if (([obj isKindOfClass:[MapLocation class]]))    
  39.         {    
  40.             MapLocation* anObj = (MapLocation*)obj;    

  41.             if ((anObj.coordinate.latitude == coord.latitude) &&    
  42.                 (anObj.coordinate.longitude == coord.longitude))    
  43.             {    
  44.                 theObj = anObj;    
  45.                 break;    
  46.             }    
  47.         }    
  48.     }    

  49.     return theObj;    
  50. }    
  51. @end  






MapKit

1. MKMapView 显示地图


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

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

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



  1. @property (readonly) NSArray *annotations; // contains id <MKAnnotation> objects  
  2. <pre name="code" class="plain">MKAnnotation protocol  
  3. @protocol MKAnnotation <NSObject>  
  4. @property (readonly) CLLocationCoordinate2D coordinate;  
  5. @optional  
  6. @property (readonly) NSString *title;  
  7. @property (readonly) NSString *subtitle;  
  8. @end  
  9. typedef {  
  10.     CLLocationDegrees latitude;  
  11.     CLLocationDegrees longitude;  
  12. } CLLocationCoordinate2D;</pre><br>  
  13. <br>  
  14. <pre></pre>  
  15. <p></p>  
  16. <pre></pre>  
  17. <p></p>  
  18. <p><span style="font-size:18px">5. 管理map view的annotations的方法</span></p>  
  19. <p><span style="font-size:18px"></span></p>  
  20. <pre name="code" class="plain">- (void)addAnnotation:(id <MKAnnotation>)annotation;  
  21. - (void)addAnnotations:(NSArray *)annotations;  
  22. - (void)removeAnnotation:(id <MKAnnotation>)annotation;  
  23. - (void)removeAnnotations:(NSArray *)annotations;</pre><br>  
  24. 6. MKMapView使用跟TableView类似的方法来重用annotation view  
  25. <p></p>  
  26. <p><span style="font-size:18px">7. Annotations通过MKAnnotationView的子类显示在地图上,默认为MKPinAnnotationView<br>  
  27. </span></p>  
  28. <p><span style="font-size:18px">8. 如果MKAnnotationView的canShowCallout设置为YES,那么点击会显示,同时会调用</span></p>  
  29. <p><span style="font-size:18px"></span></p>  
  30. <pre name="code" class="plain">- (void)mapView:(MKMapView *)sender didSelectAnnotationView:(MKAnnotationView *)aView;  
  31. //This is a great place to set up the MKAnnotationView‘s callout accessory views lazily.  
  32. </pre>  
  33. <p></p>  
  34. <p><span style="font-size:18px">9. MKAnnotationViews的创建方法跟tableviewcell在tableview中的创建类似</span></p>  
  35. <p><span style="font-size:18px"></span></p>  
  36. <pre name="code" class="plain">- (MKAnnotationView *)mapView:(MKMapView *)sender  
  37.             viewForAnnotation:(id <MKAnnotation>)annotation  
  38. {  
  39.     MKAnnotationView *aView = [sender dequeueReusableAnnotationViewWithIdentifier:IDENT];  
  40.     if (!aView) {  
  41.         aView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation  
  42.                                                 reuseIdentifier:IDENT];  
  43.         // set canShowCallout to YES and build aView’s callout accessory views here   
  44.              }  
  45.     aView.annotation = annotation; // yes, this happens twice if no dequeue  
  46.     // maybe load up accessory views here (if not too expensive)?  
  47. <span style="color:#FF0000;">    // or reset them and wait until mapView:didSelectAnnotationView: to load actual data</span>  
  48.     return aView;  
  49. }  
  50. </pre>  
  51. <p></p>  
  52. <p><span style="font-size:18px">10. MKAnnotationView的一些属性</span></p>  
  53. <p><span style="font-size:18px"></span></p>  
  54. <pre name="code" class="plain">@property id <MKAnnotation> annotation; // the annotation; treat as if readonly   
  55. @property UIImage *image; // instead of the pin, for example  
  56. @property UIView *leftCalloutAccessoryView; // maybe a UIImageView  
  57. @property UIView *rightCalloutAccessoryView; // maybe a “disclosure” UIButton   
  58. @property BOOL enabled; // NO means it ignores touch events, no delegate method, no callout   
  59. @property CGPoint centerOffset; // where the “head of the pin” is relative to the image   
  60. @property BOOL draggable; // only works if the annotation implements setCoordinate:</pre><br>  
  61. <span style="font-size:18px">11. 如果你设置一个callout accessory view为一个UIControl</span>  
  62. <p></p>  
  63. <p><span style="font-size:18px"></span></p>  
  64. <pre name="code" class="plain">e.g. aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];   
  65. The following MKMapViewDelegate method will get called when the accessory view is touched ...  

  66. - (void)mapView:(MKMapView *)sender   
  67.         annotationView:(MKAnnotationView *)aView  
  68.         calloutAccessoryControlTapped:(UIControl *)control;</pre><br>  
  69. <span style="font-size:18px">12. 使用一下代理方法来加载accessory views</span>  
  70. <p></p>  
  71. <p><span style="font-size:18px"></span></p>  
  72. <pre name="code" class="plain">-(void)mapView:(MKMapView *)sender didSelectAnnotationView:(MKAnnotationView *)aView   
  73. {  
  74.    if ([aView.leftCalloutAccessoryView isKindOfClass:[UIImageView class]]) {  
  75.           UIImageView *imageView = (UIImageView *)aView.leftCalloutAccessoryView;   
  76.           imageView.image = ...; // if you do this in a GCD queue, be careful, views are reused!  
  77.    }  
  78. }</pre>  
  79. <p></p>  
  80. <p><span style="font-size:18px">13. 地图类型</span></p>  
  81. <p><span style="font-size:18px"></span></p>  
  82. <pre name="code" class="plain">@property MKMapType mapType;  
  83. <pre name="code" class="plain">enum {    
  84.     MKMapTypeStandard = 0,    
  85.     MKMapTypeSatellite,    
  86.     MKMapTypeHybrid    
  87. };    
  88. typedef NSUInteger MKMapType;  </pre><br>  
  89. <pre></pre>  
  90. <p></p>  
  91. <pre></pre>  
  92. <p></p>  
  93. <p><span style="font-size:18px">14. 显示用户当前地址</span></p>  
  94. <p><span style="font-size:18px"></span></p>  
  95. <pre name="code" class="plain">@property BOOL showsUserLocation;  
  96. @property (readonly) BOOL isUserLocationVisible;  
  97. @property (readonly) MKUserLocation *userLocation;  
  98. MKUserLocation is an object which conforms to MKAnnotation which holds the user’s location.</pre><br>  
  99. <span style="font-size:18px">15.限制用户对地图的操作</span>  
  100. <p></p>  
  101. <p><span style="font-size:18px"></span></p>  
  102. <pre name="code" class="plain">@property BOOL zoomEnabled;  
  103. @property BOOL scrollEnabled;</pre><br>  
  104. <span style="font-size:18px">16. 控制地图的显示区域</span>  
  105. <p></p>  
  106. <p><span style="font-size:18px"></span></p>  
  107. <pre name="code" class="plain">@property MKCoordinateRegion region;  
  108. typedef struct {  
  109.     CLLocationCoordinate2D center;  
  110.     MKCoordinateSpan span;  
  111. } MKCoordinateRegion;  

  112. typedef struct {  
  113.     CLLocationDegrees latitudeDelta;  
  114.     CLLocationDegrees longitudeDelta;  
  115. }  
  116. - (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated; // animate</pre><span style="font-size:18px">注意:</span><br>  
  117. <span style="font-size:18px">你赋给region属性的值通常不是最终保存的值,在设置显示区域的时候同时也设置了缩放等级。map view不能显示任意的缩放等级,因此map view会选择一个能够尽可能显示你指定区域大小的缩放等级,然后根据此时显示的区域来保存。</span><br>  
  118. <br>  
  119. <pre name="code" class="plain">@property CLLocationCoordinate2D centerCoordinate;  
  120. - (void)setCenterCoordinate:(CLLocationCoordinate2D)center animated:(BOOL)animated;</pre><br>  
  121. <span style="font-size:18px">17. 地图载入通知</span>  
  122. <p></p>  
  123. <p><span style="font-size:18px"></span></p>  
  124. <pre name="code" class="plain">Remember that the maps are downloaded from Google earth.  
  125. - (void)mapViewWillStartLoadingMap:(MKMapView *)sender;  
  126. - (void)mapViewDidFinishLoadingMap:(MKMapView *)sender;  
  127. - (void)mapViewDidFailLoadingMap:(MKMapView *)sender withError:(NSError *)error;</pre>  
  128. <p></p>  
  129. <p><span style="font-size:18px">18. <br>  
  130. </span></p>  
  131. <p><span style="font-size:18px"><br>  
  132. </span></p>  
  133. <p><span style="font-size:18px"><br>  
  134. </span></p>  
  135. <p><span style="font-size:18px"><br>  
  136. </span></p>  
  137. <p><span style="font-size:18px"><br>  
  138. </span></p>  
  139. <p><span style="font-size:18px"><br>  
  140. </span></p>  
  141. <p><span style="font-size:18px"><br>  
  142. </span></p>  
  143. <p><br>  
  144. </p>  

  145. </pre>