自2014年共享單車出來以后共享單車熱門話題就一直沒有斷過拷泽,大家對共享單車的說法也是褒貶不一剪个,而對于從事iOS開發(fā)前兩天才拿畢業(yè)證的我來說徽曲,到目前為止我已經獨立開發(fā)完成了一套完整的共享單車iOS端APP园欣,從去年2016開始公司就開始著手做共享單車炕矮,也想從中分一勺羹朋譬。目前已經上架了4個APP(后面還有很長的隊排著等著提交審核)盐茎。基本上大致功能都一樣徙赢,換湯不換藥的那種字柠,有興趣的可以去AppStore下載一下(Camelbb、QFQ共享單車狡赐、小龍單車窑业、犀牛單車、咪吖共享單車...)
下面說一下做共享單車APP開發(fā)期間的心得吧
地圖
共享單車APP主要的界面就是地圖枕屉,對此我們采用的是高德地圖SDK
關于高德地圖的SDK配置我就不說了 百度一大把
首先是對mapView的一個基本設置和初始化常柄,這個我就不詳細說了,按需求自己設置就行了
然后就是搜索到附近的單車和一個可移動的大頭針圖標
單車標識
指定位置
1.添加單車標識和指定位置
首先我們通過后臺傳輸給你的單車定位點去添加地圖Maker(附近單車)
#pragma mark -------------------- 查找周圍單車 --------------------
- (void)updatingDrivers
{
//獲取UserDefault讀取登錄賬戶
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
NSString * userIdDt = [userDefault objectForKey:@"userId"];
NSString * startLatitude = [userDefault objectForKey:@"startLatitude"];
NSString * startLongitude = [userDefault objectForKey:@"startLongitude"];
if(userIdDt != nil){
MACoordinateRegion region;
_centerCoordinate = _mapView.region.center;
region.center= _centerCoordinate;
if(startLatitude != nil){
CLLocationCoordinate2D startPlace;
startPlace.latitude = startLatitude.floatValue;
startPlace.longitude = startLongitude.floatValue;
_centerCoordinate = startPlace;
}
MAMapRect rect = MAMapRectForCoordinateRegion(MACoordinateRegionMakeWithDistance(_centerCoordinate, latitudinalRangeMeters, longitudinalRangeMeters));
if(rect.size.width > 0 && rect.size.height > 0) {
[_bikeManager POSTNearbyBike:_centerCoordinate];
[_bikeManager searchDriversWithinMapRect:rect];
}
}
}
#pragma mark - driversManager delegate
- (void)searchDoneInMapRect:(MAMapRect)mapRect withDriversResult:(NSArray *)drivers timestamp:(NSTimeInterval)timestamp
{
self.subtitleAry = [NSMutableArray array];
if(![self.ridingState isEqualToString:@"1"]){
[_mapView removeAnnotations:_drivers];
[self.bikeCoordinateArray removeAllObjects];
NSMutableArray * currDrivers = [NSMutableArray arrayWithCapacity:[drivers count]];
[drivers enumerateObjectsUsingBlock:^(Bike * obj, NSUInteger idx, BOOL *stop) {
MAPointAnnotation * driver = [[MAPointAnnotation alloc] init];
driver.coordinate = obj.coordinate;
driver.subtitle = obj.idInfo;
driver.title = (NSString*)RoutePlanningViewControllerDestinationTitle;
NSLog(@"%@",driver.subtitle);
[self.subtitleAry addObject:driver.subtitle];
NSLog(@"%f",driver.coordinate.latitude);
NSLog(@"%f",driver.coordinate.longitude);
[currDrivers addObject:driver];
self.bikes = [[CLLocation alloc] initWithLatitude:driver.coordinate.latitude longitude:driver.coordinate.longitude];
[self.bikeCoordinateArray addObject:_bikes];
NSLog(@"h");
}];
[_mapView addAnnotations:currDrivers];
_drivers = currDrivers;
}
}
其次我們設置一個可以移動的Maker(指定位置圖標)
- (void)initCenterView
{
self.centerAnnotationView = [[MAPointAnnotation alloc] init];
self.centerAnnotationView.coordinate = _mapView.centerCoordinate;
self.centerAnnotationView.title = @"指定地點";
[_mapView addAnnotation:self.centerAnnotationView];
}
- (void)mapViewRegionChanged:(MAMapView *)mapView{
/// 如果沒有規(guī)劃路線則可以移動
if(self.isRoute == NO){
self.centerAnnotationView.coordinate = _mapView.centerCoordinate;
}
}
將單車標識和指定位置添加在地圖上
if ([[annotation title] isEqualToString:@"指定地點"])
{
annotationView.image = [UIImage imageNamed:@"指定地點"];
//設置中心點偏移搀擂,使得標注底部中間點成為經緯度對應點
annotationView.centerOffset = CGPointMake(0, -(CURRENT_SIZE(28)/2));
annotationView.zIndex = 1;
[annotationView.image setAccessibilityIdentifier:@"指定地點"];
[_mapView bringSubviewToFront:annotationView];
return annotationView;
}
if (![annotation isKindOfClass:[MANaviAnnotation class]])
{
if(self.isRoute == YES && self.haveStart == YES && self.isPop == NO){
return annotationView;
}
UIImage *image = [[UIImage alloc]init];
NSLog(@"subtitle=====%@",annotation.subtitle);
if(annotation.subtitle.integerValue == 0){
image = [UIImage imageNamed:@"單車標識"];
}else{
image = [UIImage imageNamed:@"紅包車輛標識"];
}
annotationView.image = image;
annotationView.centerOffset = CGPointMake(0, -22);
annotationView.canShowCallout = NO;
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
CGRect bounds = annotationView.bounds;
bounds.size.height -=5;
CGPoint center = annotationView.center;
center.y += 5;
[annotationView setCenter:center];
[annotationView setBounds:bounds];
}
completion:nil];
[UIView animateWithDuration:0.2
delay:0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
CGRect bounds = annotationView.bounds;
bounds.size.height +=5;
CGPoint center = annotationView.center;
center.y -= 5;
[annotationView setCenter:center];
[annotationView setBounds:bounds];
}
completion:nil];
}
2.路徑規(guī)劃
路徑規(guī)劃
在當選中一個annotation views時接口里
- (void) mapView:(MAMapView *)mapView didSelectAnnotationView:(MAAnnotationView *)view{
下面只貼出部分代碼
MAPointAnnotation *startAnnotation = [[MAPointAnnotation alloc] init];
if(self.startCoordinate.latitude == 0){
self.startCoordinate = _mapView.userLocation.location.coordinate;
startAnnotation.coordinate = _mapView.centerCoordinate;
}else{
startAnnotation.coordinate = self.startCoordinate;
}
startAnnotation.title = (NSString*)RoutePlanningViewControllerStartTitle;
startAnnotation.subtitle = [NSString stringWithFormat:@"{%f, %f}", self.startCoordinate.latitude, self.startCoordinate.longitude];
self.centerAnnotationView.coordinate = startAnnotation.coordinate;
// [_mapView addAnnotation:self.centerAnnotationView];
self.destinationCoordinate = view.annotation.coordinate;
AMapWalkingRouteSearchRequest *navi = [[AMapWalkingRouteSearchRequest alloc] init];
navi.multipath = 0;
self.startPlace = self.startCoordinate;
/* 出發(fā)點. */
navi.origin = [AMapGeoPoint locationWithLatitude:self.centerAnnotationView.coordinate.latitude
longitude:self.centerAnnotationView.coordinate.longitude];
/* 目的地. */
navi.destination = [AMapGeoPoint locationWithLatitude:self.destinationCoordinate.latitude
longitude:self.destinationCoordinate.longitude];
[self.search AMapWalkingRouteSearch:navi];
路徑規(guī)劃成功與否
#pragma mark -------------------- 路徑規(guī)劃搜索回調 --------------------
// 成功
- (void)onRouteSearchDone:(AMapRouteSearchBaseRequest *)request response:(AMapRouteSearchResponse *)response
{
//1.將兩個經緯度點轉成投影點
MAMapPoint point1 = MAMapPointForCoordinate(CLLocationCoordinate2DMake(self.startCoordinate.latitude,self.startCoordinate.longitude));
MAMapPoint point2 = MAMapPointForCoordinate(CLLocationCoordinate2DMake(self.destinationCoordinate.latitude,self.destinationCoordinate.longitude));
//2.計算距離
CLLocationDistance distance = MAMetersBetweenMapPoints(point1,point2);
NSLog(@"%f",distance);
// 距離
self.bikeDistanceString = [[NSString alloc]initWithFormat:@"%.f",distance];
self.popView.distanceLabel.text = self.bikeDistanceString;
// 到達時間
int date = distance/80;
NSString * dateStr = [[NSString alloc]initWithFormat:@"%d",date];
self.popView.dateLabel.text = dateStr;
// 保存點擊的單車距離到UserDefault 預約需要
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setObject:self.bikeDistanceString forKey:@"bikeDistance"];
[userDefault setObject:dateStr forKey:@"bikeDate"];
[userDefault synchronize];
// [self.centerAnnotationView removeFromSuperview];
// 移除彈窗
[self.loadingView removeFromSuperview];
if (response.route == nil)
{
return;
}
//解析response獲取路徑信息
self.route = response.route;
if (response.count > 0)
{
NSLog(@"%ld)",(long)response.count);
[self presentCurrentCourse];
//添加手勢到對象
[_mapView addGestureRecognizer:_tapGesture];
}
}
// 路徑規(guī)劃失敗
- (void)AMapSearchRequest:(id)request didFailWithError:(NSError *)error
{
[self.loadingView removeFromSuperview];
[LCProgressHUD showFailure:@"路徑規(guī)劃失敗"];
// 回收位置西潘、預約view
// [_mapView removeAnnotation:self.centerAnnotationView];
self.centerAnnotationView.coordinate = _mapView.centerCoordinate;
self.isPop = NO;
[AnimationManager DownToTopAnimation:self.locationView];
[self.locationView removeFromSuperview];
[AnimationManager DownToTopAnimation:self.popView];
[self.popView removeFromSuperview];
NSLog(@"Error: %@", error.domain);
}
展示路線方案
/* 展示當前路線方案. */
- (void)presentCurrentCourse
{
[self.naviRoute removeFromMapView];
MAPointAnnotation *startAnnotation = [[MAPointAnnotation alloc] init];
startAnnotation.coordinate = self.startCoordinate;
startAnnotation.title = (NSString*)RoutePlanningViewControllerStartTitle;
startAnnotation.subtitle = [NSString stringWithFormat:@"{%f, %f}", self.startCoordinate.latitude, self.startCoordinate.longitude];
NSLog(@"%f",self.startAnnotation.coordinate.latitude);
MAPointAnnotation *destinationAnnotation = [[MAPointAnnotation alloc] init];
destinationAnnotation.coordinate = self.destinationCoordinate;
destinationAnnotation.title = (NSString*)RoutePlanningViewControllerDestinationTitle;
self.destinationAnnotation = destinationAnnotation;
MANaviAnnotationType type = MANaviAnnotationTypeWalking;
self.naviRoute = [MANaviRoute naviRouteForPath:self.route.paths[0] withNaviType:type showTraffic:YES startPoint:[AMapGeoPoint locationWithLatitude:startAnnotation.coordinate.latitude longitude:startAnnotation.coordinate.longitude] endPoint:[AMapGeoPoint locationWithLatitude:self.destinationAnnotation.coordinate.latitude longitude:self.destinationAnnotation.coordinate.longitude]];
[self.naviRoute addToMapView:_mapView];
/* 縮放地圖使其適應polylines的展示. */
[_mapView setVisibleMapRect:[CommonUtility mapRectForOverlays:self.naviRoute.routePolylines]
edgePadding:UIEdgeInsetsMake(RoutePlanningPaddingEdge, RoutePlanningPaddingEdge, RoutePlanningPaddingEdge, RoutePlanningPaddingEdge)
animated:YES];
}
設置路線顏色
// 設置路線顏色
- (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id <MAOverlay>)overlay
{
if ([overlay isKindOfClass:[LineDashPolyline class]])
{
MAPolylineRenderer *polylineRenderer = [[MAPolylineRenderer alloc] initWithPolyline:((LineDashPolyline *)overlay).polyline];
polylineRenderer.lineWidth = 4;
polylineRenderer.lineJoinType = kMALineJoinRound;
polylineRenderer.lineCapType = kMALineCapRound;
polylineRenderer.strokeColor = KMainColor;
return polylineRenderer;
}
if ([overlay isKindOfClass:[MANaviPolyline class]])
{
MANaviPolyline *naviPolyline = (MANaviPolyline *)overlay;
MAPolylineRenderer *polylineRenderer = [[MAPolylineRenderer alloc] initWithPolyline:naviPolyline.polyline];
polylineRenderer.lineWidth = 4;
polylineRenderer.lineJoinType = kMALineJoinRound;
polylineRenderer.lineCapType = kMALineCapRound;
if (naviPolyline.type == MANaviAnnotationTypeWalking)
{
polylineRenderer.strokeColor = KMainColor;
}
else if (naviPolyline.type == MANaviAnnotationTypeRailway)
{
polylineRenderer.strokeColor = KMainColor;
}
else
{
polylineRenderer.strokeColor = KMainColor;
}
return polylineRenderer;
}
if ([overlay isKindOfClass:[MAMultiPolyline class]])
{
MAMultiColoredPolylineRenderer * polylineRenderer = [[MAMultiColoredPolylineRenderer alloc] initWithMultiPolyline:overlay];
polylineRenderer.lineWidth = 4;
polylineRenderer.lineJoinType = kMALineJoinRound;
polylineRenderer.lineCapType = kMALineCapRound;
polylineRenderer.strokeColors = [self.naviRoute.multiPolylineColors copy];
polylineRenderer.gradient = YES;
return polylineRenderer;
}
return nil;
}
這樣主頁地圖的主要功能就完成了 更多的是對于這兩個功能根據(jù)不同情況下的設置和展示 這個就比較復雜了 我就不一一貼了 按照自己的需求去判斷就OK了
有興趣的可以關注我的GitHub,如果喜歡的請給個Star哥倔,有建議的歡迎大家指出秸架,謝謝
我是Renjiee 我要做最騷的程序猿??????