ios - 进一步说明 "How to implement UISearchController with objective c"

标签 ios objective-c iphone uitableview cocoa-touch

我一直在尝试通过以下 stackoverflow 线程来实现 UISearchController:

How to implement UISearchController with objective c

和 Apples 的文档,但无法使其正常工作。当初始 Controller (EVTSearchViewController定义为UIViewController)符合UISearchBarDelegate, UISearchControllerDelegate, UISearchResultsUpdating, UITableViewDelegate (我也需要让它与 UITableViewDelegate 兼容,因为我让它成为另一个 UITableViewController 类型 EVTSearchResultsViewController *resultsController 的 tableView 的委托(delegate)) delegates 出现,我看到我的 .xibUISearchBarUITableView,我点击搜索栏并开始输入:

enter image description here

当我输入一个字母时,搜索栏消失,什么也没有显示:

enter image description here

首先,我不希望搜索栏消失。其次,updateSearchResultsForSearchController 似乎根本没有被调用,因为当我在搜索栏中输入时,在那里设置的 NSLog() 不会产生任何输出。

我有 .xib 用于 EVTSearchViewController 并且它有一个 UISearchBar 我正在连接到相应的属性:IBOutlet UISearchBar *searchBar 然后指向 UISearchControllers 的 searchBar:

self.searchBar = self.searchController.searchBar

还有一个UITableView,我把它放在.xib中的UISearchBar下面。我在 EVTSearchViewController 中使用的另一个 Controller 是 EVTSearchResultsViewController,它是 UITableViewController 并且它没有它的 .xib .

下面是 viewDidLoadupdateSearchResultsForSearchController 方法的代码:

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

EVTSearchViewController 中定义的相应@properties:

@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

然后,下面是 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

上面EVTSearchResultsViewController 的方法根本没有被调用,这让我觉得很奇怪,那么我们为什么需要它呢?

我尝试按照 Apple 文档推荐的方式设置 UISearchBar:

self.resultsTableView.tableHeaderView = self.searchController.searchBar;

但它给了我一个无响应的搜索框,所以当按下时没有任何反应。

请问谁能帮忙解决这个问题。上面链接的另一个问题也可以得到澄清。谢谢。

最佳答案

因此,我解决了这个问题并使用 UISearchController 实现了基本搜索.下面是我们需要做的来实现基本搜索:

  1. 创建两个 UITableViewControllers没有 .xib 的类(class)文件。是的,应该没有.xib文件,我们只是创建两个类。在下面的代码中,他们的名字是 EVTSearchViewControllerEVTSearchResultsViewController .
  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将保留搜索结果。我们不应该实现任何 UITableViewControllerEVTSearchViewController.m 中委托(delegate)方法, 但应该在 EVTSearchResultsViewController.m .

这是 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

这是 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];
// 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;
}

然后我们添加到EVTSearchViewController以下方法:

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

另一个 Controller 的 EVTSearchResultsViewController @implementation 部分看起来像这样:

@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

就是这样。如果我们需要进一步定制我们的单元格,我们应该能够通过制作 UISearchViewCell.xib 来实现。对于 EVTSearchResultsViewController ,并使用以下 viewDidLoad相反:

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

关于ios - 进一步说明 "How to implement UISearchController with objective c",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33906239/

相关文章:

iphone - 如何释放并重新初始化单例类?

ios - MonkeyTalk 无法识别 UITextfield 输入事件

ios - Cocoapods手动安装安装失败

ios - CABasicAnimation 不围绕中心缩放

ios - 按下 UIButton 时更改 JSON 数据链接

ios - MBProgressHUD showAnimated : whileExecutingBlock: not working

iphone - 读取 iPhone 运营商的信号强度

iphone - 从两个数组中获取唯一数字

ios - 定义常量字典 Objective-C

ios - 使用正则表达式验证字符串