一、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];
- }
- }