进一步阐明“如何用目标c实现UISearchController”。 [英] Further clarification of "How to implement UISearchController with objective c"

查看:49
本文介绍了进一步阐明“如何用目标c实现UISearchController”。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试通过以下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 。这是实现基本搜索所需要做的:


  1. 创建两个 UITableViewControllers 没有 .xib 文件的类。是的,应该没有 .xib 文件,我们仅创建两个类。在下面的代码中,它们的名称为 EVTSearchViewController EVTSearchResultsViewController

  2. 合一符合代表要求的控制器:< 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 *resultsControllers 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:

  1. 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 are EVTSearchViewController and EVTSearchResultsViewController.
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆