iOS Location

CoreLocation & MapKit

既然说到了定位功能,那这两个就不能分开讲,索性都放到一起讲吧

首先在你要用的controller里声明一些要用到的property
需要注意的是,请写入如下协议CLLocationManagerDelegate,MKMapViewDelegate, MKAnnotation
MKAnnotation是为了之后使用图钉时所需的协议

// 这个是用来定位的
@property (nonatomic, strong) CLLocationManager *lm;

// 用来检测定位超时的timer
@property (nonatomic, strong) NSTimer *timerLocationTimeOut;

// 用来显示的google map视图,是个IBOutlit,我就图个方便
@property (weak, nonatomic) IBOutlet MKMapView *mapView;

接下来需要对lm和mapView做一些设置,通常写在viewDidLoad里面

// 给lm开辟内存空间并初始化
self.lm = [[CLLocationManager alloc] init];

// 设置精确度为最佳
self.lm.desiredAccuracy = kCLLocationAccuracyBest;
self.lm.distanceFilter = kCLDistanceFilterNone;

// 设置delegate
self.lm.delegate = self;

// 开始定位服务
[self.lm startUpdatingLocation];

// start timer in case locate manager can't find any address
self.timerLocationTimeOut = [NSTimer scheduledTimerWithTimeInterval:45.0f 
                                                             target:self 
                                                             selector:@selector(timeOutForLocating) 
                                                             userInfo:nil 
                                                             repeats:NO];

// 定义地图类型。普通,卫星,混合
self.mapView.mapType = MKMapTypeStandard;
self.mapView.delegate = self;

// 是否显示用户当前位置(蓝色的那个点)
self.mapView.showsUserLocation = YES;

接下来就完成LocationManager更新时的delegate吧

#pragma mark - Location Delegate

// 在lm接收到更新的地理数据时下面的方法会被调用
- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    // iPhone会连续产生多个地理位置以计算精确度,如果没有新位置,那原有的地理位置就会被返回
    // 为了避免得到错误的数据,需要观察newLocation的时间戳,我们只关心5秒之内生成的新数据
    NSTimeInterval eventAge = [newLocation.timestamp timeIntervalSinceNow];

    // newLocation has a recent update that is within 5 sec
    if (abs(eventAge) < 5.0f) 
    {
        // only when accuracy is within 100 meters, ingore negative number
        if ([newLocation horizontalAccuracy] <= 100.0f && [newLocation horizontalAccuracy] > 0.0f) 
        {
            // 在得到精准数据后停止更新地理数据以便节省电池寿命
            [self.lm stopUpdatingLocation];
            
            // stop your time out location timer
            [self.timerLocationTimeOut invalidate];
            
            // deal with your newLocation
            // 这会让你的mapView显示特定的区域
            MKCoordinateRegion region = MKCoordinateRegionMake(newLocation.coordinate, MKCoordinateSpanMake(0.018, 0.018));
            [self.mapView setRegion:region animated:YES];
        }
    }
}

// 在获取地理位置失败时下面函数会被调用
// 包括但不限于用户禁止此软件使用地理功能
- (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    // deal with error
    
    // stop your time out timer
    [self.timerLocationTimeOut invalidate];
    
    [self.lm stopUpdatingLocation];
}

#pragma mark - Timer time out for locating
// 如果lm一直无法更新数据,为了节省电量,停止使用gps更新地理数据
- (void)timeOutForLocating
{
    [self.lm stopUpdatingLocation];
}

图钉的使用与自定义

在iPhone的开发中,annotation是需要你自己来写的,唯一要做的是需要遵循MKAnnotation协议
下面我实现了一个简单的annotation

#pragma mark - myAnnotation
@interface myAnotation : NSObject <MKAnnotation>
@property (nonatomic) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;

- (id)initWithCoordinate:(CLLocationCoordinate2D)coords;
@end

@implementation myAnotation
@synthesize title = _title;
@synthesize subtitle = _subtitle;
@synthesize coordinate = _coordinate;

- (id)initWithCoordinate:(CLLocationCoordinate2D)coords
{
    if (self = [super init]) {
        [self setCoordinate:coords];
    }
    return self;
}
@end

接下来你就可以使用这个自己的myAnotation类了
把它设置好加入的mapView中就会出现小图钉了

// 一个坐标的结构
typedef struct {
  CLLocationDegrees latitude;
  CLLocationDegrees longitude;
} CLLocationCoordinate2D;

// 用一个经纬坐标初始化这个Annotation
myAnotation *ann = [[myAnotation alloc] initWithCoordinate:coordinate];
ann.title = @"myTitle";
ann.subtitle = @"mySubtitle";
[self.mapView addAnnotation:ann];

如果你想要自定义自己的”图钉”你需要完成如下delegate
这个delegate在插入新的annotation是被调用


// 这个是放置普通图钉
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
// try to dequeue an existing pin view first
static NSString* BridgeAnnotationIdentifier = @"bridgeAnnotationIdentifier";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)
    [mapView dequeueReusableAnnotationViewWithIdentifier:BridgeAnnotationIdentifier];
if (!pinView)
{
   // if an existing pin view was not available, create one
   MKPinAnnotationView* customPinView = [[[MKPinAnnotationView alloc]
        initWithAnnotation:annotation reuseIdentifier:BridgeAnnotationIdentifier] autorelease];
   customPinView.pinColor = MKPinAnnotationColorPurple;
   customPinView.animatesDrop = YES;
   customPinView.canShowCallout = YES;
            
   // add a detail disclosure button to the callout which will open a new view controller page
   //
   // note: you can assign a specific call out accessory view, or as MKMapViewDelegate you can implement:
   //  - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control;
 
   UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
   [rightButton addTarget:self
                   action:@selector(showDetails:)
                   forControlEvents:UIControlEventTouchUpInside];
   customPinView.rightCalloutAccessoryView = rightButton;

   return customPinView;
}
else
{
   pinView.annotation = annotation;
}
   return pinView;
}

// 这个是放置自定义图钉
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString* SFAnnotationIdentifier = @"SFAnnotationIdentifier";
MKPinAnnotationView* pinView = (MKPinAnnotationView *)
      [mapView dequeueReusableAnnotationViewWithIdentifier:SFAnnotationIdentifier];
   if (!pinView)
{
   MKAnnotationView *annotationView = [[[MKAnnotationView alloc] 
       initWithAnnotation:annotation reuseIdentifier:SFAnnotationIdentifier] autorelease];
   annotationView.canShowCallout = YES;
 
   UIImage *flagImage = [UIImage imageNamed:@"flag.png"];
            
   annotationView.image = flagImage;
   annotationView.opaque = NO;
             
   UIImageView *sfIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SFIcon.png"]];
   annotationView.leftCalloutAccessoryView = sfIconView;
            
   return annotationView;
}
else
{
   pinView.annotation = annotation;
}
return pinView;

下面的代码会遍历mapView中的所有图钉,然后将地图zoom到中间合适的位置.

- (void)zoomToFitMapAnnotations:(MKMapView *)mapView { 
    if ([mapView.annotations count] == 0) return; 

    CLLocationCoordinate2D topLeftCoord; 
    topLeftCoord.latitude = -90; 
    topLeftCoord.longitude = 180; 

    CLLocationCoordinate2D bottomRightCoord; 
    bottomRightCoord.latitude = 90; 
    bottomRightCoord.longitude = -180; 

    for(id<MKAnnotation> annotation in mapView.annotations) { 
        topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude); 
        topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude); 
        bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude); 
        bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude); 
    } 

    MKCoordinateRegion region; 
    region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5; 
    region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;      
    region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; 

    // Add a little extra space on the sides 
    region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; 

    region = [mapView regionThatFits:region]; 
    [mapView setRegion:region animated:YES]; 
}

《iOS Location》有36个想法

  1. An Aquaponics garden may be set up indoors or outdoors
    within the backyard. Aquaponics gives an ultimate experience of staying close to nature inside clustered and chaotic cities.
    Growing fish that will easily catch diseases and parasites might
    be disheartening.

  2. If you meet someone you are searching for for the first time, you
    can begin up a conversation by centering
    on things that are non-threatening and impersonal like weather,
    the nearby e. By lifting your chin up, you are using positive body language and
    connecting with people. However, when it turns out that you’re feeling
    lonely and isolated as you don’t have enough close friendships
    and relationships in your life, you have to decide what steps you have
    to take to improve your situation.

  3. Well that is certainly where Dub Turbo solves your problems since it has a fairly
    featured beat maker, keyboard and 1000s of sounds
    that one could pick from to produce any type of music that you like.
    However, if unconditionally you aren’t pleased with your btvsolo
    purchase, you’ll be able to return it without questions
    called for a full refund within two months of purchase.
    Well there exists a way that one could do this plus it is which has a very simple, simple to operate program.

  4. Remove any muddiness from around 200-400hz employing a
    precise cut of around 1 to 4db remove any difficulty frequencies using surgical
    cuts with very narrow Q settings. And using the popularity of
    college music blogs that promote the genre equally among house and hiphop music, it’s pretty clear that individuals are accepting this new
    face-melting style. Typically 70-140 bpm; the tempo of a
    dubstep piece starts simple and then increases, increasing in tempo and adding new elements in each and every new section
    in the song.

发表评论

电子邮件地址不会被公开。 必填项已用*标注