解析搜索表未返回正确的结果

时间:2015-03-17 23:05:11

标签: objective-c uitableview parse-platform uisearchbar pfquery

我正在使用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 个答案:

答案 0 :(得分:0)

发现了这一点 - 希望它有助于其他人 - 归功于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