一、iOS后台定位
iOS的后台操作都可以在...AppDelegate.h/m文件里实现,打开所建应用的AppDelegate.m文件,可以找到函数:applicationDidEnterBackground:,从函数名就可以知道,这是应用在进入后台之后实现的函数。
有过iOS地图开发经验的都知道,iOS提供两种定位方法,分别来自不同的类库MapKit.framework和CoreLocation.framework,一种是利用MKMapView(MapKit),一种是利用CLLocationManager(CoreLocation),在先前的文章中有提到过,利用MKMapView定位是较准确的,也是比较提倡的一种方法,但是这里说到的后台定位却只能用到CLLocationManager,目前自己所能实现的就是利用它来后台定位。原因就是MKMapView虽准,但是它的定位方法:mapView:didUpdateUserLocation:需要MKMapView来唤醒,就是说,要有一张地图才能唤醒此函数,在后台无法实现,所以只能利用CLLocationManager,虽然偏移量大,但是经过对所得坐标的一些改动之后还是能勉强得到偏移量较小的位置坐标的。
首先需要一个CLLocationManager:@property (strong, nonatomic)CLLocationManager *locationManager;设置其的一些基本属性(delegate一定得设为self),在函数:locationManager:didUpdateToLocation:fromLocation:中得到定位坐标,接着便在函数:applicationDidEnterBackground:里做进入后台之后要进行的操作(启动locationManager和停止locationManager),这里建议大家用多线程实现locationManager的定位,定位功能是相当耗电的,设置定位管理器启动关闭的时间间隔有利于省电。
二、自定义MKAnnotation的callout
自定义callout,重写MKAnnotation的callout,在上面可以任意添加自己想要的控件。其实这些东西在网上都有很多好的代码,这里推荐一个自定义MKAnnotation。下载这些东西,其实就只是需要里面帮我们写好的一些重写的类,我们可以当做类库来调用它们,限于自己现在的能力,重写一些控件和View之类的还是有一定难度的,所以多看一些demo是很有用处的,然后学会怎么调用其中的类,做个聪明的懒人嘛。
看完这个demo,其实你会发现,他的用法很巧妙,首先自定义两个不同的Annotation,在添加Annotation的时候先添加一个类型的Annotation,由于callout需要点击Annotation才会显示出来,这一点被很好的利用了,在点击(选中)Annotation的一瞬间插上另一个自定义的Annotation,同时添加自定义的callout,这时便显示出自定义的callout,在点击(选中)之后又移除此Annotation,以免造成Annotation堆积重叠。实现的效果还是不错的,但是在第一次选中Annotation时,callout弹出的位置并不完全准确,另外地图还会自动跳动到另一个位置,这个目前还么发现是什么原因。接下来就根据代码来说一下吧。
首先将CalloutMapAnnotationView、CalloutMapAnnotation和BasicMapAnnotation(我只需要这三个,可根据自己的需要,解释一下这里的三个类,第一个是最主要的必不可少的,后面的两个其实是为了区分开不同的Annotation而已,自己定义的也行)的.h和.m文件导入到自己的项目中,MKMapView等其他的就不多说了,这里需要用到三个函数,首先是mapView:didSelectAnnotationView:在此函数里实现在已有的Annotation上添加可以显示自定义callout的Annotation,然后是函数:mapView:didDeselectAnnotationView:里移除刚插入的Annotation,最后也是最重要的一步,在函数mapView:mapView viewForAnnotation:里添加自定义的callout,这个时候便根据不同的自定义Annotation来添加callout,下面是一段代码示例:
- (MKAnnotationView*)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { if([annotation isKindOfClass:[CalloutMapAnnotation class]]) { CalloutMapAnnotationView *calloutMapAnnotationView = (CalloutMapAnnotationView *)[MapView dequeueReusableAnnotationViewWithIdentifier:@"CalloutAnnotation"]; calloutMapAnnotationView = [[CalloutMapAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"CalloutAnnotation"]; calloutMapAnnotationView.contentHeight = 140; NSMutableDictionary *item=[[NSMutableDictionary alloc]init]; for(NSMutableDictionary *d in self.items_array) { if(annotation.coordinate.latitude==[[d valueForKey:@"lat"]doubleValue]) { item=d; break; } } UILabel *title_label=[[UILabel alloc]initWithFrame:CGRectMake(5, 0, 300, 30)]; title_label.textColor=[UIColor whiteColor]; title_label.text=[item valueForKey:@"title"]; title_label.backgroundColor=[UIColor clearColor]; UILabel *location_label=[[UILabel alloc]initWithFrame:CGRectMake(5, 30, 180, 15)]; location_label.textColor=[UIColor whiteColor]; NSString *string=[[NSString alloc]initWithFormat:@"%@,%@",[item valueForKey:@"lat"],[item valueForKey:@"lng"]]; location_label.text=string; location_label.backgroundColor=[UIColor clearColor]; UILabel *distance_label=[[UILabel alloc]initWithFrame:CGRectMake(5, 50, 200, 15)]; distance_label.textColor=[UIColor whiteColor]; distance_label.text=[NSString stringWithFormat:@"距当前位置%@米处", [item valueForKey:@"distance"]]; distance_label.backgroundColor=[UIColor clearColor]; UILabel *category_label=[[UILabel alloc]initWithFrame:CGRectMake(5, 70, 150, 15)]; category_label.textColor=[UIColor whiteColor]; category_label.text=[item valueForKey:@"category"]; category_label.backgroundColor=[UIColor clearColor]; UILabel *vicinity_label=[[UILabel alloc]initWithFrame:CGRectMake(5, 90, 300, 15)]; vicinity_label.textColor=[UIColor whiteColor]; vicinity_label.text=[item valueForKey:@"vicinity"]; vicinity_label.backgroundColor=[UIColor clearColor]; [calloutMapAnnotationView.contentView addSubview:title_label]; [calloutMapAnnotationView.contentView addSubview:location_label]; [calloutMapAnnotationView.contentView addSubview:distance_label]; [calloutMapAnnotationView.contentView addSubview:category_label]; [calloutMapAnnotationView.contentView addSubview:vicinity_label]; calloutMapAnnotationView.parentAnnotationView = self.selectedAnnotationView; calloutMapAnnotationView.mapView = MapView; return calloutMapAnnotationView; } else if([annotation isKindOfClass:[BasicMapAnnotation class]]) { if([[annotation title]isEqualToString:@"Current Location"]) return nil; else { MKPinAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"CustomAnnotation"]; annotationView.canShowCallout = NO; annotationView.pinColor = MKPinAnnotationColorRed; return annotationView; } }else { if([[annotation title]isEqualToString:@"Current Location"]) return nil; else { MKPinAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"TypeAnnotation"]; annotationView.canShowCallout = NO; annotationView.animatesDrop=YES; annotationView.pinColor = MKPinAnnotationColorGreen; return annotationView; } } }运行截图如下:
三、消除键盘
一个非常简便的方法,直接重写函数:touchesEnded: withEvent:,这是一个响应触摸事件的函数,方法是判断触摸视图,需要用到键盘最常用的就是UITextField和UITextView这两个,当触摸到的不是这两个控件的时候,便撤掉编辑控件的第一响应属性,这样便打到了消除键盘的效果,代码示例如下:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch=[touches anyObject]; if([touch.view isKindOfClass:[UITextField class]]||[touch.view isKindOfClass:[UITextView class]]) { return; } else{ [nameText resignFirstResponder]; [typeText resignFirstResponder]; } }