解析搜索表未返回正确结果
Posted
技术标签:
【中文标题】解析搜索表未返回正确结果【英文标题】:Parse search table not returning correct results 【发布时间】:2015-03-17 23:05:11 【问题描述】:我使用 parse 作为我的应用程序的后端。我发现了几种不同的方法来使用 Parse tableview 实现搜索栏功能。我从 Parse 档案中找到的这个想法在初始视图和刷新时显示了所有对象,但是当我搜索时它不会返回正确的结果。如果我输入一个字母“a”,它会返回一些包含“a”的对象,但如果我输入更多字母或我知道应该找到的实际单词,它会返回一个空白表。搜索时还会发出警告:正在主线程上执行长时间运行的 Parse 操作。我已经工作和研究了几个星期,无法超越这一点。实现文件见代码。
#import "RecipeBookViewController.h"
#import "SearchedResultCell.h"
#import "RecipeDetailViewController.h"
#import "HotelViewController.h"
#import "Recipe.h"
static NSString *const NothingFoundCellIdentifier = @"NothingFoundCell";
@interface RecipeBookViewController ()
@end
@implementation RecipeBookViewController
@synthesize searchedBar;
@synthesize searchResults;
@synthesize recipesTable;
- (id)initWithCoder:(NSCoder *)aCoder
self = [super initWithCoder:aCoder];
if (self)
// Custom the table
// The className to query on
self.parseClassName = @"Recipe";
// The key of the PFObject to display in the label of the default cell style
self.textKey = @"name";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = NO;
// The number of objects to show per page
//self.objectsPerPage = 10;
return self;
- (void)didReceiveMemoryWarning
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
#pragma mark - UIViewController
- (void)viewDidLoad
[super viewDidLoad];
UINib *cellNib = [UINib nibWithNibName:NothingFoundCellIdentifier bundle:nil];
[self.tableView registerNib:cellNib forCellReuseIdentifier:NothingFoundCellIdentifier];
[self.searchedBar becomeFirstResponder];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(refreshTable:)
name:@"refreshTable"
object:nil];
- (void)refreshTable:(NSNotification *) notification
// Reload the recipes
[self loadObjects];
- (void)viewDidUnload
[super viewDidUnload];
// Release any retained subviews of the main view.
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"refreshTable" object:nil];
#pragma mark - UISearchBarDelegate
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
[searchResults removeAllObjects];
[self.searchedBar resignFirstResponder];
searchResults = [NSMutableArray arrayWithCapacity:10];
//#warning Put your ClassName here
PFQuery *query = [PFQuery queryWithClassName:@"Recipe"];
//#warning put key that you want to search here
[query whereKey:@"name" containsString:searchedBar.text];
NSArray *results = [query findObjects];
[searchResults addObjectsFromArray:results];
//#warning put your key here
[query orderByAscending:@"name"];
//[self queryForTable];
[self loadObjects];
#pragma mark - PFQueryTableViewController
- (void)objectsWillLoad
[super objectsWillLoad];
// This method is called before a PFQuery is fired to get more objects
- (void) objectsDidLoad:(NSError *)error
[super objectsDidLoad:error];
NSLog(@"error: %@", [error localizedDescription]);
#pragma mark - Query
- (PFQuery *)queryForTable
PFQuery *query;
if (self.searchResults == 0)
query = [PFQuery queryWithClassName:self.parseClassName];
else
query = [PFQuery queryWithClassName:self.parseClassName];
NSString *searchThis = [searchedBar.text lowercaseString];
//#warning key you wanted to search here
[query whereKeyExists:@"name"];
[query whereKey:@"name" containsString:searchThis];
[query orderByAscending:@"name"];
// If Pull To Refresh is enabled, query against the network by default.
if (self.pullToRefreshEnabled)
query.cachePolicy = kPFCachePolicyNetworkOnly;
// If no objects are loaded in memory, we look to the cache first to fill the table
// and then subsequently do a query against the network.
if (self.objects.count == 0)
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
return query;
/*
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
if (searchResults == nil)
return 0;
else if ([searchResults count] == 0)
return 1;
else
return [self.objects count];
*/
// Override to customize the look of a cell representing an object. The default is to display
// a UITableViewCellStyleDefault style cell with the label being the first key in the object.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath object:(PFObject *)object
static NSString *simpleTableIdentifier = @"RecipeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
// Configure the cell
PFFile *thumbnail = [object objectForKey:@"imageFile"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:@"recipeBoxImage2.jpg"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
UILabel *nameLabel = (UILabel*) [cell viewWithTag:101];
nameLabel.text = [object objectForKey:@"name"];
UILabel *prepTimeLabel = (UILabel*) [cell viewWithTag:102];
prepTimeLabel.text = [object objectForKey:@"prepTime"];
static NSString *LoadMoreCellIdentifier = @"LoadMoreCell";
UITableViewCell *loadcell = [self.tableView dequeueReusableCellWithIdentifier:LoadMoreCellIdentifier];
if (!cell)
loadcell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:LoadMoreCellIdentifier];
return cell;
- (void)configureSearchResult:(SearchedResultCell *)cell atIndexPath: (NSIndexPath *)indexPath object:(PFObject *)object
static NSString *simpleTableIdentifier = @"RecipeCell";
SearchedResultCell *searchcell = [self.tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (searchcell == nil)
searchcell = [[SearchedResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
// Configure the cell
PFFile *thumbnail = [object objectForKey:@"imageFile"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:@"recipeBoxImage2.jpg"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
UILabel *nameLabel = (UILabel*) [cell viewWithTag:101];
nameLabel.text = [object objectForKey:@"name"];
UILabel *prepTimeLabel = (UILabel*) [cell viewWithTag:102];
prepTimeLabel.text = [object objectForKey:@"prepTime"];
// Set CellForRowAtIndexPath
- (UITableViewCell *)searchtableView:(UITableView *)searchtableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
static NSString *CellIdentifier = @"SearchResultCell";
//Custom Cell
SearchedResultCell *cell = [searchtableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[SearchedResultCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if ([searchResults count] == 0)
//cell.mainTitle.text = @"Nothing Found";
return [self.tableView dequeueReusableCellWithIdentifier:NothingFoundCellIdentifier];
else
//#warning put your ClassName here
PFObject *object = [PFObject objectWithClassName:@"Recipe"];
object = [searchResults objectAtIndex:indexPath.row];
[self configureSearchResult:cell atIndexPath:indexPath object:object];
//[self configureSearchResult:cell atIndexPath:indexPath object:object];
return cell;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForNextPageAtIndexPath:(NSIndexPath *)indexPath
static NSString *LoadMoreCellIdentifier = @"LoadMoreCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:LoadMoreCellIdentifier];
if (!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:LoadMoreCellIdentifier];
return cell;
//// Set TableView Height for Load Next Page
//- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath
// if([self.objects count] == indexPath.row)
// // Load More Cell Height
// return 60.0;
// else
// return 80.0;
//
//
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[searchedBar resignFirstResponder];
if ([self.objects count] == indexPath.row)
[self loadNextPage];
else
PFObject *photo = [self.objects objectAtIndex:indexPath.row];
NSLog(@"%@", photo);
// Do something you want after selected the cell
#pragma mark - UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
[self.searchedBar resignFirstResponder];
//- (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
//
// // Remove the row from data model
// PFObject *object = [self.objects objectAtIndex:indexPath.row];
// [object deleteInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
// [self refreshTable:nil];
// ];
//
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if ([segue.identifier isEqualToString:@"showRecipeDetail"])
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
PFObject *object = [self.objects objectAtIndex:indexPath.row];
Recipe *recipe = [[Recipe alloc] init];
recipe.name = [object objectForKey:@"name"];
recipe.imageFile = [object objectForKey:@"imageFile"];
recipe.prepTime = [object objectForKey:@"prepTime"];
recipe.ingredients = [object objectForKey:@"ingredients"];
recipe.instructions = [object objectForKey:@"instructions"];
recipe.servings = [object objectForKey:@"servings"];
recipe.hotelSite = [object objectForKey:@"hotelSite"];
recipe.recipeType = [object objectForKey:@"recipeType"];
destViewController.recipe = recipe;
@end
【问题讨论】:
【参考方案1】:找到这个 - 希望它可以帮助其他人 - 归功于 Bizzi-Body
https://github.com/Bizzi-Body/ParseTutorial-Part-2
//
// GourmetChefViewController.m
//
// Created by RedMac on 3/19/15.
//
#import "RecipeBookViewController.h"
@interface RecipeBookViewController ()
NSMutableArray *totalStrings;
NSMutableArray *filteredStrings;
BOOL isFiltered;
@end
@implementation RecipeBookViewController
#pragma mark -
#pragma mark UIViewController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
[super viewDidLoad];
self.mySearchBar.delegate =self;
self.myTableView.delegate = self;
self.myTableView.dataSource=self;
[self retrieveFromParse];
- (void) retrieveFromParse
PFQuery *retrieveRecipes = [PFQuery queryWithClassName:@"Recipe"];
[retrieveRecipes whereKeyExists:@"name"];
[retrieveRecipes findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
if (!error)
NSLog(@"%@", objects);
totalStrings = [[NSMutableArray alloc] initWithArray:objects];
[self.myTableView reloadData];
];
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
return 1;
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *) searchText
if (searchText.length ==0)
isFiltered =NO;
else
isFiltered =YES;
filteredStrings=[[NSMutableArray alloc]init];
for(PFObject *element in totalStrings)
NSString * str = [element objectForKey:@"name"];
NSLog(@"%@", NSStringFromClass([element class])); // you thought that totalStrings
// contained NSString objects,
// but it contains PFObjects.
NSRange stringRange =[str rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (stringRange.location !=NSNotFound)
// you need to add the PFObject back to make your cellForRowAtIndexPath: method
// work.
[filteredStrings addObject:element]; // used to be :str
[self.myTableView reloadData];
//table view datasource and delegate method.....
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section
if (isFiltered)
return [filteredStrings count];
return [totalStrings count];
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"RecipeCell";
UITableViewCell *cell= [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (!cell)
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if(!isFiltered)
PFObject *tempObject =[totalStrings objectAtIndex: indexPath.row];
cell.textLabel.text = [tempObject objectForKey:@"name"];
else
PFObject *tempObject2 =[filteredStrings objectAtIndex: indexPath.row];
cell.textLabel.text =[tempObject2 objectForKey:@"name"];
return cell;
- (void)didReceiveMemoryWarning
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
@end
【讨论】:
以上是关于解析搜索表未返回正确结果的主要内容,如果未能解决你的问题,请参考以下文章
ElasticSearch - SpringBoot整合ES:解析搜索返回字段
UITableView / UISearchBar 返回不正确的结果