iOS——UISearchController(地图联想搜索Demo)

简介

UISearchController是iOS 8 之后推出的一个新的控件, 用于创建搜索条, 及管理搜索事件, 使用这个, 我们可以很容易的创建属于自己的搜索框。搜索框在app开发中是非常常见的,比如说我们要搜索一个地点。这里就利用到了这个控件,简单记录一下。
iOS——UISearchController(地图联想搜索Demo)_第1张图片

简单使用

我们就以上面这个Demo举例实现一个简单的UISearchViewController的使用。
UISearchController 让用户在 UISearchBar 上输入搜索关键词,展示搜索结果或者进行其他操作。UISearchController 把两个控制器(UIViewController)连在一起。父控制器放置 UISearchBar 控件。当用户点击搜索框时,UISearchBar 会移到屏幕顶部;输入搜索关键词,UISearchBar 下面出现子控制器的view
所以UISearchController是很少单独使用的,一般都是配合其他的控件进行使用,实现联想搜索结果的展示栏一般是使用UITableView实现的。

控件属性

// 初始化方法, 参数是展示搜索结果的控制器, 如果是在当前控制器展示搜索结果, 就传nil
- (instancetype)initWithSearchResultsController:(nullable UIViewController *)searchResultsController;

// 负责更新搜索结果的代理, 需要遵循 UISearchResultsUpdating 协议
@property (nullable, nonatomic, weak) id <UISearchResultsUpdating> searchResultsUpdater;

// 搜索控制器是否是活跃状态, 当在一个控制器展示搜索结果的时候, 可以此来判断返回的数据源
@property (nonatomic, assign, getter = isActive) BOOL active;
// 控制器代理  遵循 UISearchControllerDelegate协议
@property (nullable, nonatomic, weak) id <UISearchControllerDelegate> delegate;
// 当搜索框激活时, 是否添加一个透明视图
@property (nonatomic, assign) BOOL dimsBackgroundDuringPresentation __TVOS_PROHIBITED; 
@property (nonatomic, assign) BOOL obscuresBackgroundDuringPresentation NS_AVAILABLE_IOS(9_1); // default is YES
// 当搜索框激活时, 是否隐藏导航条
@property (nonatomic, assign) BOOL hidesNavigationBarDuringPresentation;     // default is YES

@property (nullable, nonatomic, strong, readonly) UIViewController *searchResultsController;
@property (nonatomic, strong, readonly) UISearchBar *searchBar;

这里注意: UISearchController 在使用的时候, 需要设置为全局的变量或者控制器属性, 使其生命周期与控制器相同; 如果设置为局部变量, 会提前销毁, 导致无法使用.

创建Demo的一些属性

这里的采用了高德的搜索SDK——高德开发手册

//
//  SearchViewController.h
//  ShareParking
//
//  Created by 差不多先生 on 2022/3/26.
//

#import <UIKit/UIKit.h>
#import <AMapSearchKit/AMapSearchKit.h>
#import <MAMapKit/MAMapKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface SearchViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating, AMapSearchDelegate>

@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) UISearchController *searchController;
// 数据源数组
@property (nonatomic, strong) NSMutableArray *datas;
// 搜索结果数组
@property (nonatomic, strong) NSMutableArray *results;

// 搜索接口
@property (nonatomic, strong) AMapSearchAPI* search;
@property (nonatomic, retain) MAUserLocation* currentLocation;
// 搜索字段
@property (nonatomic, strong) NSString* searchString;
@end

NS_ASSUME_NONNULL_END

首先我们要继承UISearchResultsUpdating协议。

初始化位置

这里因为我们默认搜索类型是停车场,所以初始化数据时,会自动检索当前位置附近的停车场。
以下是使用高德获取的数据。

 (void)getParking {
    _searchString = @"停车场";
    _datas = [[NSMutableArray alloc] init];
    self.search = [[AMapSearchAPI alloc] init];
    self.search.delegate = self;
    AMapPOIAroundSearchRequest *request = [[AMapPOIAroundSearchRequest alloc] init];
    //当前位置
    request.location = [AMapGeoPoint locationWithLatitude:34.15408339 longitude:108.90631727];
    request.keywords            = _searchString;
    /* 按照距离排序. */
    request.sortrule            = 0;
    request.requireExtension    = YES;
    // 启动任务
    [self.search AMapPOIAroundSearch:request];
}
- (void)onPOISearchDone:(AMapPOISearchBaseRequest *)request response:(AMapPOISearchResponse *)response {
    int j = 0;
    if(response.pois.count == 0) {
        NSLog(@"111");
        return;
    }
     
    //通过 AMapPOISearchResponse 对象处理搜索结果
     
    [self.datas removeAllObjects];
    //解析response获取POI信息,具体解析见 Demo
    for (AMapPOI *p in response.pois) {
        j = 0;
        for (int i = 0; i < _datas.count; i++) {
            AMapPOI* a = _datas[i];
            if ([p.name isEqual:a.name]) {
                j = 1;
            }
        }
        if (j == 0) {
            //搜索结果存在数组
            [self.datas addObject:p];
        }
        
    }
    dispatch_async(dispatch_get_main_queue(), ^{
       // UI更新代码
        [self.tableView reloadData];
    });
    


}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
    // 这里通过searchController的active属性来区分展示数据源是哪个
    if (self.searchController.active) {
        
        return self.results.count ;
    }
    
    return self.datas.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID"];
    if (cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellID"];
    }
    if ([_datas[0] class] == [AMapPOI class]) {
        AMapPOI *p = self.datas[indexPath.row];
        cell.textLabel.text = p.name;
    } else {
        AMapTip* p = self.datas[indexPath.row];
        cell.textLabel.text = p.name;
    }
    
    
    return cell;
}

iOS——UISearchController(地图联想搜索Demo)_第2张图片
就可以达成这样一个效果。

利用SearchBar进行搜索

这里我们需要将SearchBar加入tableView最上面的位置。

 // 创建UISearchController, 这里使用当前控制器来展示结果
        UISearchController *search = [[UISearchController alloc]initWithSearchResultsController:nil];
        // 设置结果更新代理
        search.searchResultsUpdater = self;
        [self getParking];
        // 因为在当前控制器展示结果, 所以不需要这个透明视图
        search.dimsBackgroundDuringPresentation = NO;
        self.searchController = search;
        // 将searchBar赋值给tableView的tableHeaderView
        search.searchBar.placeholder = @"选择停车位位置";
        self.tableView.tableHeaderView = search.searchBar;

接下来我们需要调用协议方法:
这个方法会在我们输入时调用,我们可以在这里根据输入文字重新搜索位置,并且刷新tableView的数据。

// 输入响应函数
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
    
    _searchString = searchController.searchBar.text;
    [self inputAddress];
   
}
- (void)inputAddress {
    AMapInputTipsSearchRequest *tips = [[AMapInputTipsSearchRequest alloc] init];
    tips.keywords = _searchString;
    tips.city     = @"西安";
    tips.cityLimit = YES;
    [self.search AMapInputTipsSearch:tips];
}
/* 输入提示回调. */
- (void)onInputTipsSearchDone:(AMapInputTipsSearchRequest *)request response:(AMapInputTipsSearchResponse *)response {
    if(response.count == 0) {
        NSLog(@"111");
        return;
    } else {
        [_datas removeAllObjects];
        for (int i = 0; i < response.count; i++) {
            AMapTip* p = response.tips[i];
            [_datas addObject:p];
        }
    }
    dispatch_async(dispatch_get_main_queue(), ^{
       // UI更新代码
        [self.tableView reloadData];
    });
}
//@interface AMapTip : AMapSearchObject
/poi的id
//@property (nonatomic, copy) NSString *uid;
/名称
//@property (nonatomic, copy) NSString *name;
/区域编码
//@property (nonatomic, copy) NSString *adcode;
/所属区域
//@property (nonatomic, copy) NSString *district;
/地址
//@property (nonatomic, copy) NSString *address;
/位置
//@property (nonatomic, copy) AMapGeoPoint *location;
/类型码, since 4.5.0. 对应描述可下载参考官网文档 http://a.amap.com/lbs/static/zip/AMap_API_Table.zip。
//@property (nonatomic, copy) NSString *typecode;
- (void)onPOISearchDone:(AMapPOISearchBaseRequest *)request response:(AMapPOISearchResponse *)response {
    int j = 0;
    if(response.pois.count == 0) {
        NSLog(@"111");
        return;
    }
     
    //通过 AMapPOISearchResponse 对象处理搜索结果
     
    [self.datas removeAllObjects];
    //解析response获取POI信息,具体解析见 Demo
    for (AMapPOI *p in response.pois) {
        j = 0;
        for (int i = 0; i < _datas.count; i++) {
            AMapPOI* a = _datas[i];
            if ([p.name isEqual:a.name]) {
                j = 1;
            }
        }
        if (j == 0) {
            //搜索结果存在数组
            [self.datas addObject:p];
        }
        
    }
    dispatch_async(dispatch_get_main_queue(), ^{
       // UI更新代码
        [self.tableView reloadData];
    });
    


}

然后就可以实现联想搜索地点了,这个控件这里用的比较简单,后面如果深入使用会来补充的。
iOS——UISearchController(地图联想搜索Demo)_第3张图片

你可能感兴趣的:(iOS,ios,objective-c,开发语言)