最近用了融云IM的SDK,但是里面关于定位部分,iOS没有位置搜索, android是有的。所以...自定义呗。
先看下效果:
RPReplay_Final1640311497.gif
主要基于这三个SDK:
#import
#import
#import
1. 处理扩展。
在聊天界面处理下面代码。
/*!
扩展功能板的点击回调
@param pluginBoardView 输入扩展功能板View
@param tag 输入扩展功能(Item)的唯一标示
*/
- (void)pluginBoardView:(RCPluginBoardView *)pluginBoardView clickedItemWithTag:(NSInteger)tag {
switch (tag) {
case PLUGIN_BOARD_ITEM_LOCATION_TAG: {
RCDLocationViewController *vc = [[RCDLocationViewController alloc] init];
vc.delegate = self;
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:vc];
navi.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:navi animated:YES completion:nil];
}
break;
default:
[super pluginBoardView:pluginBoardView clickedItemWithTag:tag];
break;
}
}
/*!
地理位置选择完成之后的回调
@param locationPicker 地理位置选取的ViewController
@param location 位置的二维坐标
@param locationName 位置的名称
@param mapScreenShot 位置在地图中的缩略图
@discussion
如果您需要重写地理位置选择的界面,当选择地理位置完成后,需要调用此回调通知RCConversationViewController定位已完成,可以进一步生成位置消息并发送。
*/
- (void)locationPicker:(RCLocationPickerViewController *)locationPicker
didSelectLocation:(CLLocationCoordinate2D)location
locationName:(NSString *)locationName
mapScreenShot:(UIImage *)mapScreenShot {
RCLocationMessage *locationMessage =
[RCLocationMessage messageWithLocationImage:mapScreenShot location:location locationName:locationName];
[self sendMessage:locationMessage pushContent:nil];
}
didSelectLocation:(CLLocationCoordinate2D)location
locationName:(NSString *)locationName
mapScreenShot:(UIImage *)mapScreenShot
这个方法是原来融云里面的delegate,就没有去单独写了。
2. 自定义地图界面
#import
#import "XNViewController.h"
NS_ASSUME_NONNULL_BEGIN
/*!
地理位置选择完成之后的回调
*/
@protocol RCDLocationViewControllerDelegate
/*!
地理位置选择完成之后的回调
@param locationPicker 地理位置选取的ViewController
@param location 位置的二维坐标
@param locationName 位置的名称
@param mapScreenShot 位置在地图中的缩略图
@discussion
如果您需要重写地理位置选择的界面,当选择地理位置完成后,需要调用此回调通知RCConversationViewController定位已完成,可以进一步生成位置消息并发送。
*/
- (void)locationPicker:(RCLocationPickerViewController *)locationPicker
didSelectLocation:(CLLocationCoordinate2D)location
locationName:(NSString *)locationName
mapScreenShot:(UIImage *)mapScreenShot;
@end
@interface RCDLocationViewController : XNViewController
@property(nonatomic, weak) id delegate;
@end
NS_ASSUME_NONNULL_END
#import "RCDLocationViewController.h"
#import
#import
#import
@interface RCDLocationViewController ()
//定位
@property (nonatomic, strong) AMapLocationManager *locationManager;
//地图
@property (nonatomic, strong) MAMapView *mapView;
//大头针
@property (nonatomic, strong) MAPointAnnotation *annotation;
//逆地理编码
@property (nonatomic, strong) AMapReGeocodeSearchRequest *regeo;
//逆地理编码使用的
@property (nonatomic, strong) AMapSearchAPI *search;
@property (nonatomic, strong) NSMutableArray *dataArrary;
@property (nonatomic, strong) UITableView *mTableView;
@property (nonatomic, assign) CLLocationCoordinate2D currentGPSCoordinate;
@property (nonatomic, strong) UITextField *textFiled;
@property (nonatomic, copy) NSString *currentCity;
@end
@implementation RCDLocationViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.mapView.showsUserLocation = true;
self.mapView.userTrackingMode = MAUserTrackingModeFollow;
[self addObserver];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
- (void)ActionForBackButton:(UIButton *)button {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)setUpUI {
[self setNaviTitle:@"选择位置"];
[self addNavigationBarBackButton:nil normal:IMAGENAME(@"ic_back") selected:IMAGENAME(@"ic_back")];
[self.view addSubview:self.mapView];
[self.view addSubview:self.textFiled];
[self.view addSubview:self.mTableView];
self.search.delegate = self;
[self startLocation];
[self.nextButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
}
- (void)startLocation {
_currentGPSCoordinate = kCLLocationCoordinate2DInvalid;
[self showHUD:@"定位中..."];
[self.mapView removeAnnotations:_mapView.annotations];
__weak typeof (self) weakself = self;
[self.locationManager requestLocationWithReGeocode:YES completionBlock:^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error) {
[weakself hideHUD];
if (error) {
[weakself showHUDError:@"定位失败,请重新定位"];
}
if (regeocode != nil) {
NSLog(@"%@",[NSString stringWithFormat:@"地址信息:\n%@",regeocode]);
}
self.currentGPSCoordinate = location.coordinate;
// 添加定位点的大头针
MAPointAnnotation *annotation = [[MAPointAnnotation alloc]init];
annotation.coordinate = self.currentGPSCoordinate;
[self.mapView addAnnotation:annotation];
[annotation setLockedToScreen:YES];
annotation.lockedScreenPoint = CGPointMake(self.mapView.bounds.size.width/2, self.mapView.bounds.size.height/2);
// 设置地图
[self.mapView setZoomLevel:15.5 animated:YES];
[self.mapView selectAnnotation:annotation animated:YES];
[self.mapView setCenterCoordinate:self.currentGPSCoordinate animated:NO];
[self searchAllPOIAround:self.currentGPSCoordinate];
}];
}
- (void)searchAllPOIAround:(CLLocationCoordinate2D) coordinate{
AMapPOIAroundSearchRequest *request = [[AMapPOIAroundSearchRequest alloc] init];
request.sortrule = 0;
request.offset = 30;
request.location = [AMapGeoPoint locationWithLatitude:coordinate.latitude longitude:coordinate.longitude];
request.radius = 500;
[self.search AMapPOIAroundSearch:request];
}
//地图区域改变完成后会调用此接口
- (void)mapView:(MAMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
//非法的时候需返回
if (!CLLocationCoordinate2DIsValid(_currentGPSCoordinate)) {
return;
}
[self searchAllPOIAround: _mapView.centerCoordinate];
//搜索POI
[self searchAllPOIAround:_mapView.centerCoordinate];
}
///注意:大头针是跟TableView的Cell一样具有重用机制的,处理不好界面会有很多消失不去的大头针。
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id)annotation {
if ([annotation isKindOfClass:[MAPointAnnotation class]]) {
NSString *pointReuseIndetifier = @"pointReuseIndetifier";
MAPinAnnotationView *annotationView = ((MAPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndetifier]);
if (annotationView == nil) {
annotationView = [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndetifier];
}
annotationView.canShowCallout = NO;
annotationView.animatesDrop = YES;
[annotationView setDraggable:NO];
return annotationView;
}
return nil;
}
- (void)onPOISearchDone:(AMapPOISearchBaseRequest *)request response:(AMapPOISearchResponse *)response {
if (!_dataArrary) {
_dataArrary = [[NSMutableArray alloc]init];
}
[_dataArrary removeAllObjects];
[_dataArrary addObjectsFromArray:response.pois];
_currentCity = _dataArrary[0].city;
[_mTableView reloadData];
}
//搜索框激活时,使用提示搜索
-(void)updateSearchResultsForSearchController:(UITextField *)searchTextField
{
//发起输入提示搜索
AMapInputTipsSearchRequest *tipsRequest = [[AMapInputTipsSearchRequest alloc] init];
//关键字
tipsRequest.keywords = searchTextField.text;
//城市
tipsRequest.city = _currentCity;
//执行搜索
[_search AMapInputTipsSearch: tipsRequest];
}
//实现输入提示的回调函数
- (void)onInputTipsSearchDone:(AMapInputTipsSearchRequest*)request response:(AMapInputTipsSearchResponse *)response
{
if(response.tips.count == 0)
{
return;
}
//通过AMapInputTipsSearchResponse对象处理搜索结果
//先清空数组
if (!self.dataArrary) {
self.dataArrary = [[NSMutableArray alloc]init];
}
[self.dataArrary removeAllObjects];
for (AMapTip *p in response.tips) {
//把搜索结果存在数组
[self.dataArrary addObject:p];
}
// _isSelected = NO;
//刷新表视图
[self.mTableView reloadData];
}
#pragma tableViewDelegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return _dataArrary.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"adressCell" forIndexPath:indexPath];
AMapPOI *poi = _dataArrary[indexPath.section];
cell.textLabel.font = [UIFont systemFontOfSize:14];
cell.textLabel.textColor = UIColor.grayColor;
cell.textLabel.text = poi.name;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
AMapPOI *poi = _dataArrary[indexPath.section];
///这里处理选中
if (_delegate != nil) {
// @autoreleasepool {
// "http://restapi.amap.com/v3/staticmap?location=" + longitude + "," + latitude +
// "&zoom=17&scale=2&size=150*150&markers=mid,,A:" + longitude + ","
// + latitude + "&key=" + "AMAP_KEY";
NSString *url = [self toImage:poi.location.longitude latitude:poi.location.latitude];
// UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url]]];
NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
UIImage *image = [UIImage imageWithData:data];
[_delegate locationPicker:nil didSelectLocation:CLLocationCoordinate2DMake(poi.location.latitude, poi.location.longitude) locationName:poi.name mapScreenShot:image];
// }
}
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma textFiled Delegate
- (void)textFieldDidEndEditing:(UITextField *)textField {
[self updateSearchResultsForSearchController:textField];
}
#pragma setter and getter
- (AMapLocationManager *)locationManager {
if (!_locationManager) {
_locationManager = [[AMapLocationManager alloc]init];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyHundredMeters];
_locationManager.locationTimeout = 5;
_locationManager.reGeocodeTimeout = 5;
_locationManager.delegate = self;
}
return _locationManager;
}
- (AMapReGeocodeSearchRequest *)regeo {
if (!_regeo) {
_regeo = [[AMapReGeocodeSearchRequest alloc]init];
_regeo.requireExtension = YES;
}
return _regeo;
}
- (AMapSearchAPI *)search {
if (!_search) {
_search = [[AMapSearchAPI alloc]init];
_search.delegate = self;
}
return _search;
}
- (UITableView *)mTableView {
if (!_mTableView) {
_mTableView = [[UITableView alloc]initWithFrame:CGRectMake(0, kScreenH/2 + 100,kScreenW, (kScreenH - NaviBarStatusBarHeight)/2 - 100 )];
_mTableView.delegate = self;
_mTableView.dataSource = self;
_mTableView.backgroundColor = UIColor.clearColor;
_mTableView.showsHorizontalScrollIndicator = NO;
[ZQShareMethod setExtraCellLineHidden:_mTableView];
[_mTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"adressCell"];
}
return _mTableView;
}
- (MAMapView *)mapView {
if (!_mapView) {
_mapView = [[MAMapView alloc]initWithFrame:CGRectMake(0, NaviBarStatusBarHeight, kScreenW, (kScreenH - NaviBarStatusBarHeight)/2)];
_mapView.delegate = self;
_mapView.compassOrigin = CGPointMake(_mapView.compassOrigin.x, 22);
_mapView.scaleOrigin = CGPointMake(_mapView.scaleOrigin.x, 22);
_mapView.showsScale = NO;
_mapView.zoomLevel = 15;
}
return _mapView;
}
- (UITextField *)textFiled {
if (!_textFiled) {
_textFiled = [[UITextField alloc]initWithFrame:CGRectMake(15, kScreenH/2 + 50, kScreenW - 30, 40)];
_textFiled.delegate = self;
_textFiled.borderStyle = UITextBorderStyleRoundedRect;
_textFiled.placeholder = @"搜索地点";
_textFiled.returnKeyType = UIReturnKeyDone;
[_textFiled addTarget:self action:@selector(updateSearchResultsForSearchController:) forControlEvents:UIControlEventValueChanged];
}
return _textFiled;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[self.view endEditing:YES];
return YES;
}
- (NSString *)toImage:(double)longitude latitude:(double)latitude {
return [NSString stringWithFormat:@"https://restapi.amap.com/v3/staticmap?location=%f,%f&zoom=12&size=300*150&&markers=mid,,A:%f,%f&key=%@",longitude,latitude,longitude,latitude,[NSString stringWithFormat:@"893421fc7552922a75fabd1cf7823c68"]];
}
- (void)addObserver{
//增加监听,当键盘出现或改变时收出消息
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardDidShowNotification
object:nil];
//增加监听,当键退出时收出消息
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
//当键盘出现或改变时调用
- (void)keyboardWillShow:(NSNotification *)aNotification {
NSDictionary* info = [aNotification userInfo];
//kbSize即為鍵盤尺寸 (有width, height)
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;//得到鍵盤的高度
self.textFiled.frame = CGRectMake(15, kScreenH - (kbSize.height + SafeAreaBottomHeight + 10), kScreenW - 30, 40);
}
//当键退出时调用
- (void)keyboardWillHide:(NSNotification *)aNotification {
[self dismissTouchView];
self.textFiled.frame = CGRectMake(15, kScreenH/2 + 50, kScreenW - 30, 40);
}
- (void)doinsomethingwithtouchViewdismiss {
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
}
@end
比较忙,时间匆匆。等空了再来完善吧,只此记录。