最近項(xiàng)目要用到微信發(fā)送地址查看地址的功能桐罕,完成的也差不多了,基本上大部分功能都實(shí)現(xiàn)了桂敛,現(xiàn)在整理出來(lái)功炮,也有一些想和大家一起交流的地方,希望彼此都有所收獲术唬。
先講講UISearchController
說(shuō)實(shí)話我之前很少有用到它薪伏,基本上都是自定義的,但是我看微信的效果雖然不肯定就是UISeachController但是基本上是差不多的粗仓,所以我也就踩踩這個(gè)坑毅该,其實(shí)了解了以后使用還是相當(dāng)方便的博秫。
問(wèn)題1:點(diǎn)擊searchbar的時(shí)候,searchbar飛到視圖外面
解決辦法
self.definesPresentationContext = YES;
問(wèn)題2:點(diǎn)擊searchbar的時(shí)候眶掌,searchbar上方也就是狀態(tài)欄的部分是透明的挡育,和UISearchController的顏色是一樣的。
這個(gè)情況在默認(rèn)情況下是不會(huì)出現(xiàn)的朴爬,但是我們開發(fā)的使用經(jīng)常使用這樣一句代碼self.edgesForExtendedLayout = UIRectEdgeNone;
來(lái)使tableView頂?shù)絥avigationbar而不是延展到navigationbar里面即寒,并且往往在基類中做這一設(shè)置。
解決方法:
self.edgesForExtendedLayout = UIRectEdgeAll;
再就是去掉searchBar底部有一條黑線
_searchController.searchBar.subviews.firstObject.subviews.firstObject.layer.borderColor = [UIColor colorWithHexString:@"c6c6c6"].CGColor;
_searchController.searchBar.subviews.firstObject.subviews.firstObject.layer.borderWidth = .5;
地圖功能
進(jìn)入界面默認(rèn)顯示定位地址召噩,下方的POI列表也是默認(rèn)顯示定位附近的母赵,大頭針是一直都指向地圖的中心點(diǎn),之后定位的變化不會(huì)再引起POI列表的變化具滴,只有拖動(dòng)地圖凹嘲,改變大頭針指向的位置才會(huì)更新POI列表。
poi列表 也就是地圖下方的列表
這里的POI列表构韵,我是采用的反地理編碼的方式周蹭,但是有局限性,也就是百度地圖只返回最多十條記錄疲恢,這就有點(diǎn)尷尬了凶朗,百度地圖有提供其他查詢附近POI的方式(像以坐標(biāo)為原點(diǎn)xxx米為半徑等),但是這些方式都有一個(gè)共同點(diǎn) 显拳,需要加入一個(gè)關(guān)鍵字棚愤,也就是說(shuō),我不能把附近所有的POI都列出來(lái)杂数,只能根據(jù)類別搜索宛畦,像搜美食,酒店這個(gè)意思揍移。
暫時(shí)沒(méi)找到好辦法刃永,沒(méi)法像微信那樣獲取很多記錄,有知道的望能告知羊精。
定位
當(dāng)點(diǎn)擊右下角的定位按鈕會(huì)將用戶的位置顯示在中心點(diǎn)處,百度地圖有四種地位模式
1) BMKUserTrackingModeNone :普通定位模式囚玫,顯示我的位置喧锦,我的位置圖標(biāo)和地圖都不會(huì)旋轉(zhuǎn)
2) BMKUserTrackingModeFollow : 定位跟隨模式,我的位置始終在地圖中心抓督,我的位置圖標(biāo)會(huì)旋轉(zhuǎn)燃少,地圖不會(huì)旋轉(zhuǎn)
3) BMKUserTrackingModeFollowWithHeading : 定位羅盤模式,我的位置始終在地圖中心铃在,我的位置圖標(biāo)和地圖都會(huì)跟著旋轉(zhuǎn)
4) BMKUserTrackingModeHeading:普通定位+定位羅盤模式阵具,顯示我的位置碍遍,我的位置始終在地圖中心,我的位置圖標(biāo)會(huì)旋轉(zhuǎn)阳液,地圖不會(huì)旋轉(zhuǎn)怕敬。即在普通定位模式的基礎(chǔ)上顯示方向。
我這里用的是普通定位模式帘皿,我認(rèn)為發(fā)送地址重要的是找地址东跪,并不需要了解我面朝南還是朝北。鹰溜。但是在查看地址的時(shí)候虽填,是十分有必要的。
定位這里有個(gè)小細(xì)節(jié)曹动,就是微信在移動(dòng)地圖的時(shí)候斋日,他會(huì)用當(dāng)前地圖的中心點(diǎn)和用戶定位的地點(diǎn)做比較,如果誤差在一定范圍墓陈,那么地圖右下角表示已經(jīng)在當(dāng)前位置的按鈕就會(huì)成選中狀態(tài)恶守。這里我直接用的百度地圖的計(jì)算API,這里我設(shè)定的是100m跛蛋。
BMKMapPoint centerPoint = BMKMapPointForCoordinate(centerlocation);
BMKMapPoint userPoint = BMKMapPointForCoordinate(self.locService.userLocation.location.coordinate);
CLLocationDistance distance = BMKMetersBetweenMapPoints(centerPoint,userPoint);
if (distance <=100) {
self.locationBtn.selected = YES;
}else{
self.locationBtn.selected = NO;
}
記得將.m文件修改為.mm
搜索地址
這個(gè)地方我一開始想?yún)⒖嘉⑿虐镜模斎氲刂罚谌珖?guó)檢索赊级,基于這個(gè)需求我在百度地圖開發(fā)文檔中找相關(guān)接口押框,結(jié)果發(fā)現(xiàn)并沒(méi)有全國(guó)搜索這一個(gè)接口,只有按城市搜索理逊,結(jié)果使用后我認(rèn)為這就是我要找的橡伞。它會(huì)默認(rèn)在你設(shè)置的城市中搜索,當(dāng)前城市沒(méi)有再在全國(guó)范圍內(nèi)搜索晋被,我認(rèn)為這是比較合理的兑徘,否則,單純的全國(guó)搜索還需要考慮權(quán)重的問(wèn)題羡洛,如果我想搜索 “體育館”理所應(yīng)當(dāng)我想的是在當(dāng)前城市搜索體育館挂脑,如果我真想搜其他地方的體育館,可以加上城市名搜索欲侮。
城市POI搜索代碼
BMKCitySearchOption *option = [[BMKCitySearchOption alloc]init];
option.pageIndex = 0;
option.pageCapacity = 30;
option.keyword = self.keyword;//搜索關(guān)鍵字
option.city = self.userCity.length == 0?@"青島市":self.userCity; //userCity是用戶定位地址
BOOL flag = [self.poiSearch poiSearchInCity:option];
if(flag)
{
NSLog(@"周邊檢索發(fā)送成功");
}
else
{
NSLog(@"周邊檢索發(fā)送失敗");
}
關(guān)鍵字高亮
這里我是將關(guān)鍵字 拆分成每一個(gè)單獨(dú)的字符進(jìn)行匹配的崭闲,效果如圖
這里有個(gè)坑我有必要提一下,一開始做這個(gè)功能的時(shí)候威蕉,我第一時(shí)間想到的是- (NSRange)rangeOfString:(NSString *)searchString;
這個(gè)方法刁俭,在字符串中查找某個(gè)字串的NSRange,但是這有個(gè)問(wèn)題就是這個(gè)方法只返回第一個(gè)的位置韧涨,也就是如果這一行中有兩個(gè)相同子符牍戚,他也永遠(yuǎn)只返回第一個(gè)的侮繁,那好吧,看看兄妹方法有沒(méi)有能適用的如孝,結(jié)果找到了這個(gè)方法- (NSRange)rangeOfString:(NSString *)searchString options:(NSStringCompareOptions)mask range:(NSRange)rangeOfReceiverToSearch;
這個(gè)是可以指定范圍查找宪哩,看起來(lái)很完美。但是暑竟。斋射。。但荤。我在實(shí)際使用過(guò)程中罗岖,出現(xiàn)了隨機(jī)的NSNotFound,但是我用containsString
做了判斷了,并且也是確確實(shí)實(shí)存在的腹躁。
圖中可見桑包,上下兩個(gè)結(jié)構(gòu)基本一樣,但是第二個(gè)就出現(xiàn)了NSNotFound,最后的解決方案是遍歷字符串自己構(gòu)建NSRange纺非,并存放到數(shù)組里哑了,再遍歷NSRange數(shù)組設(shè)置高亮
NSMutableAttributedString *attributeStr = [[NSMutableAttributedString alloc] initWithString:origintext];
NSMutableArray *indexArray = @[].mutableCopy;
for(int i =0; i < [origintext length]; I++)
{
NSString *temp = [origintext substringWithRange:NSMakeRange(i,1)];
if ([keyword containsString:temp]) {
[indexArray addObject:[NSValue valueWithRange:NSMakeRange(i, 1)]];
}
}
[indexArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSRange range = [obj rangeValue];
[attributeStr addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:23/255.0f green:182/255.0f blue:0 alpha:1] range:range];
}];
查看地址模塊
這個(gè)就比較簡(jiǎn)單了,傳入需要顯示的坐標(biāo)烧颖,反地理編碼獲取POI的name弱左,address顯示出來(lái)就可以了
這里的定位模式是BMKUserTrackingModeHeading:普通定位+定位羅盤模式 主要方便導(dǎo)航到目的地。
這里有幾個(gè)功能
- 顯示路線
- 街景
-
外部地圖導(dǎo)航
顯示路線
這里顯示的是駕車路線炕淮,雖然不一定是最優(yōu)路線拆火,但是起碼無(wú)論你步行還是騎行都是能走通的,這個(gè)在這里也只是顯示個(gè)大概涂圆,真正的導(dǎo)航還是跳轉(zhuǎn)到各類地圖應(yīng)用吧们镜。
發(fā)起請(qǐng)求
BMKPlanNode* start = [[BMKPlanNode alloc]init];
start.pt = self.coordinate;
BMKPlanNode* end = [[BMKPlanNode alloc]init];
end.pt = self.locationService.userLocation.location.coordinate;
BMKDrivingRoutePlanOption *option = [[BMKDrivingRoutePlanOption alloc]init];
option.from = start;
option.to = end;
//發(fā)起檢索
BOOL flag = [self.routeSearcher drivingSearch:option];
if(flag) {
NSLog(@"駕車檢索發(fā)送成功");
} else {
NSLog(@"駕車檢索發(fā)送失敗");
}
繪制路線
[self.mapView removeOverlays:self.mapView.overlays];
BMKDrivingRouteLine *plan = (BMKDrivingRouteLine *)[result.routes objectAtIndex:0];
int size = (int)[plan.steps count];
int pointCount = 0;
for (int i = 0; i< size; i++) {
BMKDrivingStep *step = [plan.steps objectAtIndex:i];
pointCount += step.pointsCount;
}
BMKMapPoint *points = new BMKMapPoint[pointCount];
int k = 0;
for (int i = 0; i< size; i++) {
BMKDrivingStep *step = [plan.steps objectAtIndex:i];
for (int j= 0; j<step.pointsCount; j++) {
points[k].x = step.points[j].x;
points[k].y = step.points[j].y;
k++;
}
}
BMKPolyline *polyLine = [BMKPolyline polylineWithPoints:points count:pointCount];
[self.mapView addOverlay:polyLine];
當(dāng)然你需要先在mapVIew的代理方法``(BMKOverlayView *)mapView:(BMKMapView *)mapView viewForOverlay:(id )overlay` 自定義樣式
街景
這個(gè)沒(méi)啥要說(shuō)的,很簡(jiǎn)單润歉,需要單獨(dú)下載SDK
調(diào)用地圖應(yīng)用導(dǎo)航
這里我用的是 百度地圖 ,高的地圖 ,蘋果地圖, 默認(rèn)調(diào)用的都是駕車路線模狭,當(dāng)然在地圖里面可以更改,使用url的方法調(diào)用踩衩,[[UIApplication sharedApplication] openURL:url]
嚼鹉,調(diào)用之前最好用[[UIApplication sharedApplication] canOpenURL:url]
判斷一下,別忘了加Schemes 驱富。
百度地圖:baidumap
高德地圖:iosamap