进一步阐明“如何用目标c实现UISearchController”。 [英] Further clarification of "How to implement UISearchController with objective c"
问题描述
我一直在尝试通过以下stackoverflow线程实现 UISearchController
:
当我键入一个字母时,搜索栏消失,什么也没有显示:
首先,我会不希望搜索栏消失。其次,似乎根本没有调用 updateSearchResultsForSearchController
,因为在我设置的 NSLog()
不会产生任何输出
对于 EVTSearchViewController,我有
.xib
。 code>,并且它有一个 UISearchBar
我正在连接到相应的属性: IBOutlet UISearchBar * searchBar
其中然后使它指向UISearchControllers的searchBar:
self.searchBar = self.searchController.searchBar
我也将 UITableView
放在 .xib
中的> UISearchBar 。我在 EVTSearchViewController
中使用的另一个控制器是 EVTSearchResultsViewController
,它是 UITableViewController
,但没有
下面是 viewDidLoad
和 updateSearchResultsForSearchController
方法:
-(void)viewDidLoad
{
_resultsController = [[EVTSearchResultsViewController alloc] init];
_searchController = [[UISearchController alloc] initWithSearchResultsController:_resultsController];
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.placeholder = nil;
[self.searchController.searchBar sizeToFit];
self.searchBar = self.searchController.searchBar;
//我们想成为过滤表的委托,因此两个表都调用didSelectRowAtIndexPath
self.resultsController.tableView.delegate = self;
self.searchController.delegate =自我;
self.searchController.dimsBackgroundDuringPresentation = YES; //默认是YES
self.searchController.searchBar.delegate = self; //这样我们就可以监视文本更改以及其他更改
//搜索现在仅显示视图控制器。因此,普通视图控制器
//表示语义适用。也就是说,该表示将沿视图控制器
//层次结构前进,直到找到根视图控制器或定义了表示上下文的根视图控制器为止。
//
self.definesPresentationContext = YES; //知道要在哪里显示UISearchController
}
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController {
//更新基于过滤的数组在搜索文本
NSString上* searchText = searchController.searchBar.text;
NSLog(@ searchText:%@,searchText);
if(searchText == nil){
//如果为空,搜索结果与原始数据相同
self.searchResults = [[[EVTItemStore sharedStore] allItems] mutableCopy];
} else {
NSMutableArray * searchResults = [[NSMutableArray alloc] init];
NSArray * allEvents = [[EVTItemStore sharedStore] allItems];
NSLog(@ allEvents:%@,allEvents);
用于(EVTItem * allEvents中的事件){
/ * if([event.number containsString:searchText] || [[[phoneMO.closrr_idfilteredId] containsString:searchText] || [[ phoneMO.contact.fullname lowercaseString] containsString:[searchText lowercaseString]]){
[searchResults addObject:phoneMO];
} * /
if([event.eventName containsString:searchText]){
[searchResults addObject:event];
}
}
self.searchResults = searchResults;
}
//将过滤后的结果移交给我们的搜索结果表
EVTSearchResultsViewController * resultsController =(EVTSearchResultsViewController *)self.searchController.searchResultsController;
resultsController.filteredEvents = self.searchResults;
[resultsController.tableView reloadData];
}
相应的 @properties
在 EVTSearchViewController
中定义:
@interface EVTSearchViewController()
@属性(弱,非原子)IBOutlet UISearchBar * searchBar;
@property(非原子的,强的)UISearchController * searchController;
@property(非原子的,强的)EVTSearchResultsViewController * resultsController;
@property(非原子的,强的)NSMutableArray * searchResults;
//用于状态恢复
@property BOOL searchControllerWasActive;
@property BOOL searchControllerSearchFieldWasFirstResponder;
@end
然后,这是<$ c $的代码c> EVTSearchResultsViewController :
#import EVTSearchResultsViewController.h
@implementation EVTSearchResultsViewController
-(实例类型)init
{
//调用超类的指定初始化器
self = [super initWithStyle:UITableViewStylePlain];
if(self){
}
return self;
}
-(void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell类]
forCellReuseIdentifier:@ UISearchViewCell];
}
-(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
//处理所有可以重新创建的资源。
}
-(NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return [self.filteredEvents count] ;
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell =
[ tableView dequeueReusableCellWithIdentifier:@ UISearchViewCell
forIndexPath:indexPath];
cell.textLabel.text = self.filteredEvents [indexPath.row];
返回单元格;
}
@end
<$ c的方法上面的$ c> EVTSearchResultsViewController 根本没有被调用,这对我来说很奇怪,那为什么我们根本需要它呢?
我尝试按照Apple文档推荐的方式设置 UISearchBar
:
self。 resultsTableView.tableHeaderView = self.searchController.searchBar;
但是它给了我一个无响应的搜索框,所以当按下时什么也没发生。
任何人都可以帮助解决这个问题。上面链接的其他问题也可以得到澄清。谢谢。
因此,我解决了这个问题,并使用 UISearchController $ c实现了基本搜索$ c>。这是实现基本搜索所需要做的:
- 创建两个
UITableViewControllers
没有.xib
文件的类。是的,应该没有.xib
文件,我们仅创建两个类。在下面的代码中,它们的名称为EVTSearchViewController
和EVTSearchResultsViewController
。 - 合一符合代表要求的控制器:
< UISearchBarDelegate,UISearchControllerDelegate,UISearchResultsUpdating>
这是 EVTSearchViewController
的头文件的代码:
#import< UIKit / UIKit.h>
@interface EVTSearchViewController:UITableViewController< UISearchBarDelegate,UISearchControllerDelegate,UISearchResultsUpdating>
@end
这是 EVTSearchResultsViewController
的标头:
#import< UIKit / UIKit.h>
@interface EVTSearchResultsViewController:UITableViewController
@property(nonatomic,strong)NSMutableArray * filteredEvents;
@end
NSMutableArray * filteredEvents
将保存搜索结果。我们不应该在 EVTSearchViewController.m
中实现任何 UITableViewController
委托方法,而应该在中实现EVTSearchResultsViewController.m
。
这是 EVTSearchViewController
的顶部:
#import EVTSearchViewController.h
#import EVTSearchResultsViewController.h
//导入存储`EVTItem`对象类的类
#import EVTItemStore.h
#import EVTItem.h
@interface EVTSearchViewController()
@property (非原子性强)UISearchController * searchController;
//我们创建了此类
@property(非原子的,强的)EVTSearchResultsViewController * resultsController;
//用于保存搜索结果的数组
@property(非原子的,强的)NSMutableArray * searchResults;
@end
这是的代码EVTSearchViewController
的 viewDidLoad:
方法:
-(void)viewDidLoad
{
[super viewDidLoad];
self.resultsController = [[EVTSearchResultsViewController alloc] init];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsController];
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.placeholder = nil;
[self.searchController.searchBar sizeToFit];
//这行代码非常重要。这里我们使用的是苹果文档的
//建议。 UITableViewController具有tableView属性,所以
// //我们只是将tableView的标头设置为苹果的UISearchController的`searchBar属性
self.tableView.tableHeaderView = self.searchController.searchBar;
self.searchController.delegate =自我;
//默认值为YES
self.searchController.dimsBackgroundDuringPresentation = YES;
//这样我们就可以监视文本更改和其他更改
self.searchController.searchBar.delegate = self;
//知道要在哪里显示UISearchController
self.definesPresentationContext = YES;
}
然后我们将其添加到 EVTSearchViewController
以下方法:
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController {
//根据搜索文字
NSString更新过滤后的数组* searchText = searchController.searchBar.text;
if(searchText == nil){
//如果为空,搜索结果应与原始数据相同
self.searchResults = [[[EVTItemStore sharedStore] allItems ] mutableCopy];
} else {
NSMutableArray * searchResults = [[NSMutableArray alloc] init];
// [[[EVTItemStore sharedStore] allItems]消息检索
//我在数据存储EVTItemStore中拥有的所有对象
NSArray * allEvents = [[EVTItemStore sharedStore] allItems] ;
// EVTItem类具有一个属性eventName,我们正在使用
//进行搜索,然后将其添加到我们的resultResults数组
中,以用于(EVTItem * allEvents中的事件){ b $ b if([event.eventName containsString:searchText]){
[searchResults addObject:event];
}
}
self.searchResults = searchResults;
}
//将过滤后的结果移交给我们的搜索结果表
EVTSearchResultsViewController * resultsController =(EVTSearchResultsViewController *)self.searchController.searchResultsController;
resultsController.filteredEvents = self.searchResults;
[resultsController.tableView reloadData];
}
另一个控制器的 EVTSearchResultsViewController
@implementation部分看起来像这样:
@implementation EVTSearchResultsViewController
-(instancetype)init
{
//调用超类的指定初始化器
self = [super initWithStyle:UITableViewStylePlain];
if(self){
}
return self;
}
-(NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return [self.filteredEvents count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell =
[tableView dequeueReusableCellWithIdentifier:@ UISearchViewCell
forIndexPath:indexPath];
EVTItem * event = self.filteredEvents [indexPath.row];
cell.textLabel.text = event.eventName;
个返回单元格;
}
-(void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell类]
forCellReuseIdentifier:@ UISearchViewCell];
}
@end
就是这样。如果我们需要进一步自定义单元格,则可以通过为 EVTSearchResultsViewController
制作 UISearchViewCell.xib
来实现,并使用以下 viewDidLoad
代替:
-(void)viewDidLoad
{
[super viewDidLoad];
//加载NIB文件
UINib * nib = [UINib nibWithNibName:@ UISearchViewCell bundle:nil];
//注册包含单元格
的NIB [self.tableView registerNib:nib forCellReuseIdentifier:@ UISearchViewCell];
}
I have been trying to implement UISearchController
by following stackoverflow thread:
How to implement UISearchController with objective c
and Apples's documentation, but can't make it working. When the initial controller (EVTSearchViewController
which is defined as UIViewController
) that complies with UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating, UITableViewDelegate
(I needed to make it compliant with UITableViewDelegate
too, since I am making it a delegate of the other UITableViewController
type EVTSearchResultsViewController *resultsController
s tableView) delegates is presented, I see my .xib
with the UISearchBar
and UITableView
, I click the search bar and start typing:
When I type one letter, search bar disappears and nothing is shown:
First, I do not want the search bar to disappear. Second, updateSearchResultsForSearchController
seems not to be called at all since NSLog()
set up there does not produce any output when I am typing in the search bar.
I have .xib
for the EVTSearchViewController
and it has a UISearchBar
that I am connecting to the respective property: IBOutlet UISearchBar *searchBar
which is then made to point to the UISearchControllers' searchBar:
self.searchBar = self.searchController.searchBar
There is also UITableView
that I put below the UISearchBar
in the .xib
. Another controller that I am using inside EVTSearchViewController
is EVTSearchResultsViewController
, it is UITableViewController
and it does not have its .xib
.
Below is the code for viewDidLoad
and updateSearchResultsForSearchController
methods:
- (void)viewDidLoad
{
_resultsController = [[EVTSearchResultsViewController alloc] init];
_searchController = [[UISearchController alloc] initWithSearchResultsController:_resultsController];
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.placeholder = nil;
[self.searchController.searchBar sizeToFit];
self.searchBar = self.searchController.searchBar;
// we want to be the delegate for our filtered table so didSelectRowAtIndexPath is called for both tables
self.resultsController.tableView.delegate = self;
self.searchController.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = YES; // default is YES
self.searchController.searchBar.delegate = self; // so we can monitor text changes + others
// Search is now just presenting a view controller. As such, normal view controller
// presentation semantics apply. Namely that presentation will walk up the view controller
// hierarchy until it finds the root view controller or one that defines a presentation context.
//
self.definesPresentationContext = YES; // know where you want UISearchController to be displayed
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
// update the filtered array based on the search text
NSString *searchText = searchController.searchBar.text;
NSLog(@"searchText: %@", searchText);
if (searchText == nil) {
// If empty the search results are the same as the original data
self.searchResults = [[[EVTItemStore sharedStore] allItems] mutableCopy];
} else {
NSMutableArray *searchResults = [[NSMutableArray alloc] init];
NSArray *allEvents = [[EVTItemStore sharedStore] allItems];
NSLog(@"allEvents: %@", allEvents);
for (EVTItem *event in allEvents) {
/*if ([event.number containsString:searchText] || [[phoneMO.closrr_id filteredId] containsString:searchText] || [[phoneMO.contact.fullname lowercaseString] containsString:[searchText lowercaseString]]) {
[searchResults addObject:phoneMO];
}*/
if ([event.eventName containsString:searchText]) {
[searchResults addObject:event];
}
}
self.searchResults = searchResults;
}
// hand over the filtered results to our search results table
EVTSearchResultsViewController *resultsController = (EVTSearchResultsViewController *)self.searchController.searchResultsController;
resultsController.filteredEvents = self.searchResults;
[resultsController.tableView reloadData];
}
The respective @properties
defined in EVTSearchViewController
:
@interface EVTSearchViewController ()
@property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
@property (nonatomic, strong) UISearchController *searchController;
@property (nonatomic, strong) EVTSearchResultsViewController *resultsController;
@property (nonatomic, strong) NSMutableArray *searchResults;
// For state restoration
@property BOOL searchControllerWasActive;
@property BOOL searchControllerSearchFieldWasFirstResponder;
@end
Then, here is the code for EVTSearchResultsViewController
:
#import "EVTSearchResultsViewController.h"
@implementation EVTSearchResultsViewController
- (instancetype)init
{
// Call the superclass's designated initializer
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:@"UISearchViewCell"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return [self.filteredEvents count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:@"UISearchViewCell"
forIndexPath:indexPath];
cell.textLabel.text = self.filteredEvents[indexPath.row];
return cell;
}
@end
The methods of EVTSearchResultsViewController
above are not called at all which makes look very strange for me, why do we need it at all, then?
I tried to set UISearchBar
the way Apple docs recommend:
self.resultsTableView.tableHeaderView = self.searchController.searchBar;
but it gives me a non-responsive search box, so when pressing nothing happens.
Could anyone, please, help with resolving the question. The other question linked above can also be clarified then. Thank you.
So, I solved the issue and implemented basic search with UISearchController
. Here is what we need to do to implement the basic search:
- Create two
UITableViewControllers
classes with NO.xib
files. Yes, there should be no.xib
files and we are just creating two classes. In the code below their names areEVTSearchViewController
andEVTSearchResultsViewController
. - Make one of the controllers to comply with the delegates:
<UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating>
Here is the code for the header file of EVTSearchViewController
:
#import <UIKit/UIKit.h>
@interface EVTSearchViewController : UITableViewController <UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating>
@end
Here is the EVTSearchResultsViewController
's header:
#import <UIKit/UIKit.h>
@interface EVTSearchResultsViewController : UITableViewController
@property (nonatomic, strong) NSMutableArray *filteredEvents;
@end
The NSMutableArray *filteredEvents
will hold the results of the search. We should NOT implement any of the UITableViewController
delegate methods in EVTSearchViewController.m
, but should in EVTSearchResultsViewController.m
.
Here is the top part of EVTSearchViewController
:
#import "EVTSearchViewController.h"
#import "EVTSearchResultsViewController.h"
// Importing the class that stores `EVTItem` object classes
#import "EVTItemStore.h"
#import "EVTItem.h"
@interface EVTSearchViewController ()
@property (nonatomic, strong) UISearchController *searchController;
// We created this class
@property (nonatomic, strong) EVTSearchResultsViewController *resultsController;
// array to hold the results of the search
@property (nonatomic, strong) NSMutableArray *searchResults;
@end
Here is the code for EVTSearchViewController
's viewDidLoad:
method:
- (void)viewDidLoad
{
[super viewDidLoad];
self.resultsController = [[EVTSearchResultsViewController alloc] init];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsController];
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.placeholder = nil;
[self.searchController.searchBar sizeToFit];
// This line of code is very important. Here we are using apple docs'
// suggestion. UITableViewController has tableView property, so
// we are just setting tableView`s header to apples' UISearchController`s' `searchBar property
self.tableView.tableHeaderView = self.searchController.searchBar;
self.searchController.delegate = self;
// default is YES
self.searchController.dimsBackgroundDuringPresentation = YES;
// so we can monitor text changes + other changes
self.searchController.searchBar.delegate = self;
// know where you want UISearchController to be displayed
self.definesPresentationContext = YES;
}
Then we add to EVTSearchViewController
the following method:
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
// update filtered array based on the search text
NSString *searchText = searchController.searchBar.text;
if (searchText == nil) {
// If empty the search results should be the same as the original data
self.searchResults = [[[EVTItemStore sharedStore] allItems] mutableCopy];
} else {
NSMutableArray *searchResults = [[NSMutableArray alloc] init];
// [[EVTItemStore sharedStore] allItems] message retrieves
// all of the objects that I have in datastore EVTItemStore
NSArray *allEvents = [[EVTItemStore sharedStore] allItems];
// EVTItem class has a property eventName which we are using
// for searching, then adding it to our searchResults array
for (EVTItem *event in allEvents) {
if ([event.eventName containsString:searchText]) {
[searchResults addObject:event];
}
}
self.searchResults = searchResults;
}
// hand over the filtered results to our search results table
EVTSearchResultsViewController *resultsController = (EVTSearchResultsViewController *)self.searchController.searchResultsController;
resultsController.filteredEvents = self.searchResults;
[resultsController.tableView reloadData];
}
Another controller's EVTSearchResultsViewController
@implementation part looks like this:
@implementation EVTSearchResultsViewController
- (instancetype)init
{
// Call the superclass's designated initializer
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
}
return self;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return [self.filteredEvents count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:@"UISearchViewCell"
forIndexPath:indexPath];
EVTItem *event = self.filteredEvents[indexPath.row];
cell.textLabel.text = event.eventName;
return cell;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:@"UISearchViewCell"];
}
@end
That's it. If we need to further customize our cells, we should be able to do it by making UISearchViewCell.xib
for EVTSearchResultsViewController
, and using the following viewDidLoad
instead:
- (void)viewDidLoad
{
[super viewDidLoad];
// Load the NIB file
UINib *nib = [UINib nibWithNibName:@"UISearchViewCell" bundle:nil];
// Register this NIB which contains the cell
[self.tableView registerNib:nib forCellReuseIdentifier:@"UISearchViewCell"];
}
这篇关于进一步阐明“如何用目标c实现UISearchController”。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!