iOS 仿写微信发送地址模块

效果图

最近项目要用到微信发送地址查看地址的功能,完成的也差不多了,基本上大部分功能都实现了,现在整理出来,也有一些想和大家一起交流的地方,希望彼此都有所收获。

github地址

先讲讲UISearchController

说实话我之前很少有用到它,基本上都是自定义的,但是我看微信的效果虽然不肯定就是UISeachController但是基本上是差不多的,所以我也就踩踩这个坑,其实了解了以后使用还是相当方便的。

问题1:点击searchbar的时候,searchbar飞到视图外面
现象

解决办法
self.definesPresentationContext = YES;

问题2:点击searchbar的时候,searchbar上方也就是状态栏的部分是透明的,和UISearchController的颜色是一样的。
现象

这个情况在默认情况下是不会出现的,但是我们开发的使用经常使用这样一句代码self.edgesForExtendedLayout = UIRectEdgeNone;来使tableView顶到navigationbar而不是延展到navigationbar里面,并且往往在基类中做这一设置。

解决方法
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;

地图功能

进入界面默认显示定位地址,下方的POI列表也是默认显示定位附近的,大头针是一直都指向地图的中心点,之后定位的变化不会再引起POI列表的变化,只有拖动地图,改变大头针指向的位置才会更新POI列表。

poi列表 也就是地图下方的列表

这里的POI列表,我是采用的反地理编码的方式,但是有局限性,也就是百度地图只返回最多十条记录,这就有点尴尬了,百度地图有提供其他查询附近POI的方式(像以坐标为原点xxx米为半径等),但是这些方式都有一个共同点 ,需要加入一个关键字,也就是说,我不能把附近所有的POI都列出来,只能根据类别搜索,像搜美食酒店这个意思。

暂时没找到好办法,没法像微信那样获取很多记录,有知道的望能告知。

定位

当点击右下角的定位按钮会将用户的位置显示在中心点处,百度地图有四种地位模式

1) BMKUserTrackingModeNone :普通定位模式,显示我的位置,我的位置图标和地图都不会旋转
2) BMKUserTrackingModeFollow : 定位跟随模式,我的位置始终在地图中心,我的位置图标会旋转,地图不会旋转
3) BMKUserTrackingModeFollowWithHeading : 定位罗盘模式,我的位置始终在地图中心,我的位置图标和地图都会跟着旋转
4) BMKUserTrackingModeHeading:普通定位+定位罗盘模式,显示我的位置,我的位置始终在地图中心,我的位置图标会旋转,地图不会旋转。即在普通定位模式的基础上显示方向。

我这里用的是普通定位模式,我认为发送地址重要的是找地址,并不需要了解我面朝南还是朝北。。但是在查看地址的时候,是十分有必要的。

定位这里有个小细节,就是微信在移动地图的时候,他会用当前地图的中心点用户定位的地点做比较,如果误差在一定范围,那么地图右下角表示已经在当前位置的按钮就会成选中状态。这里我直接用的百度地图的计算API,这里我设定的是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

搜索地址

这个地方我一开始想参考微信,输入地址,在全国检索,基于这个需求我在百度地图开发文档中找相关接口,结果发现并没有全国搜索这一个接口,只有按城市搜索,结果使用后我认为这就是我要找的。它会默认在你设置的城市中搜索,当前城市没有再在全国范围内搜索,我认为这是比较合理的,否则,单纯的全国搜索还需要考虑权重的问题,如果我想搜索 “体育馆”理所应当我想的是在当前城市搜索体育馆,如果我真想搜其他地方的体育馆,可以加上城市名搜索。

城市POI搜索代码

  BMKCitySearchOption *option = [[BMKCitySearchOption alloc]init];
    option.pageIndex = 0;
    option.pageCapacity = 30;
    option.keyword = self.keyword;//搜索关键字
    option.city = self.userCity.length == 0?@"青岛市":self.userCity; //userCity是用户定位地址
    BOOL flag = [self.poiSearch poiSearchInCity:option];
    if(flag)
    {
        NSLog(@"周边检索发送成功");
    }
    else
    {
        NSLog(@"周边检索发送失败");
    }
关键字高亮

这里我是将关键字 拆分成每一个单独的字符进行匹配的,效果如图

关键字高亮

这里有个坑我有必要提一下,一开始做这个功能的时候,我第一时间想到的是- (NSRange)rangeOfString:(NSString *)searchString; 这个方法,在字符串中查找某个字串的NSRange,但是这有个问题就是这个方法只返回第一个的位置,也就是如果这一行中有两个相同子符,他也永远只返回第一个的,那好吧,看看兄妹方法有没有能适用的,结果找到了这个方法- (NSRange)rangeOfString:(NSString *)searchString options:(NSStringCompareOptions)mask range:(NSRange)rangeOfReceiverToSearch; 这个是可以指定范围查找,看起来很完美。但是。。。。我在实际使用过程中,出现了随机的NSNotFound,但是我用containsString做了判断了,并且也是确确实实存在的。

图中可见,上下两个结构基本一样,但是第二个就出现了NSNotFound,最后的解决方案是遍历字符串自己构建NSRange,并存放到数组里,再遍历NSRange数组设置高亮

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

查看地址模块


这个就比较简单了,传入需要显示的坐标,反地理编码获取POI的name,address显示出来就可以了

这里的定位模式是BMKUserTrackingModeHeading:普通定位+定位罗盘模式 主要方便导航到目的地。

这里有几个功能

  • 显示路线
  • 街景
  • 外部地图导航


显示路线

这里显示的是驾车路线,虽然不一定是最优路线,但是起码无论你步行还是骑行都是能走通的,这个在这里也只是显示个大概,真正的导航还是跳转到各类地图应用吧。

发起请求

   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;
    
    //发起检索
    BOOL flag = [self.routeSearcher drivingSearch:option];
    if(flag) {
        NSLog(@"驾车检索发送成功");
    } else {
        NSLog(@"驾车检索发送失败");
    }
    

绘制路线

     [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];

当然你需要先在mapVIew的代理方法``(BMKOverlayView *)mapView:(BMKMapView *)mapView viewForOverlay:(id )overlay` 自定义样式

街景

这个没啥要说的,很简单,需要单独下载SDK

调用地图应用导航

这里我用的是 百度地图 ,高的地图 ,苹果地图, 默认调用的都是驾车路线,当然在地图里面可以更改,使用url的方法调用,[[UIApplication sharedApplication] openURL:url],调用之前最好用[[UIApplication sharedApplication] canOpenURL:url]判断一下,别忘了加Schemes

百度地图:baidumap
高德地图:iosamap

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容