0

my app uses a SearchGraphical to search for registered users in the app ... My problem is that when I go to do research shows me the duplicate results as:

Name Search: Francesca Result: Francesca (1 cell) Francesca (2 Cell)

**09/14/2013 22:18:17.817 Unipot v.02 [63396: a0b] Successfully retrieved 1 scores.
09/14/2013 22:18:17.818 Unipot v.02 [63396: a0b] Content: Antonella Folino
09/14/2013 22:18:17.818 Unipot v.02 [63396: a0b] Content: francesca Folino
09/14/2013 22:18:17.818 Unipot v.02 [63396: a0b] Content: francesca Folino
09/14/2013 22:18:17.819 Unipot v.02 [63396: a0b] Content: francesca Folino**

I do not understand why. This problem arises when you type in the search bar is done quickly.

In addition, the app crashes after a short time by returning to this notice:

**Terminating apt two to uncaught exception 'NSRangeException', reason: '*** - [__NSArrayM objectAtIndex:]: index 10 beyond bounds [0 .. 9] '**

This is my file. M Can you help me??

#import "Ricerca.h"
#import "Custom.h"

@interface Ricerca () <UISearchDisplayDelegate, UISearchBarDelegate>
@property (nonatomic, strong) UISearchDisplayController *searchController;
@property (nonatomic, strong) NSMutableArray *searchResults;

@end

@implementation Ricerca

- (void)viewDidLoad {
    [super viewDidLoad];
    [self loadObjects];
   self.searchResults = [NSMutableArray array];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        self.parseClassName = @"_User";



        self.paginationEnabled = YES;

        self.loadingViewEnabled = NO;

       self.objectsPerPage = 10;
    }
    return self;
}



- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait || UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {



    UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (!cell)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"Cell"];
    }


    // Configure the cell

    UIColor *color = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:0.0];
    cell.detailTextLabel.backgroundColor = color;
    cell.textLabel.backgroundColor = color;


    if (tableView == self.tableView) {
        cell.textLabel.text = [object objectForKey:@"username"];
    }

    else {


        PFObject *searchedUser = [self.searchResults objectAtIndex:indexPath.row];
        NSString *content = [searchedUser objectForKey:@"username"];
        cell.textLabel.text = content;

        NSLog(@"Content: %@", content);


    }

    return cell;

}


-(void)filterResults:(NSString *)searchTerm {

    [self.searchResults removeAllObjects];

    PFQuery *query = [PFQuery queryWithClassName:@"_User"];
    [query whereKey:@"username" containsString:searchTerm];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            // The find succeeded.
            NSLog(@"Successfully retrieved %d scores.", objects.count);
            [self.searchResults addObjectsFromArray:objects];
            [self.searchDisplayController.searchResultsTableView    reloadData];


        } else {
            // Log details of the failure
            NSLog(@"Error: %@ %@", error, [error userInfo]);
        }


    }];

    }

-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
    [self filterResults:searchString];
    return YES;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    if (tableView == self.tableView) {
        return self.objects.count;

    } else {
        return self.searchResults.count;
    }
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (tableView == self.tableView) {
        [super tableView:tableView didSelectRowAtIndexPath:indexPath];

    } else {

        [super tableView:tableView didSelectRowAtIndexPath:indexPath];

    }
}
kAiN
  • 2,559
  • 1
  • 26
  • 54

1 Answers1

1

In your filterResults: method you are calling [self.searchResults addObjectsFromArray:objects];, this will add those results to what is already there. In the case where this method is getting hit multiple times before the first query finishes you could end up with the following scenario:

  • filter 1: "Fran"
  • clear results
  • start query 1
  • filter 2: "Franc"
  • clear results
  • start query 2
  • filter 2 finishes in background: add single result to array (contents 1 item)
  • filter 1 finishes in background: add single result to array (contents 2 items)

As you can see, there's no way to be sure when a query will finish, they might come back in a different order, and might not come back before you call the method again.

In this case it is hard to know what to do, you could empty self.searchResults in the success block, but in a case like above the final contents will be for the first query instead of the second query.

You could implement some kind of cancel/ignore-results option, or add a delay to the start of the query and hope for the best. Either way I would suggest reading up on threading issues and async operations.

Timothy Walters
  • 16,866
  • 2
  • 41
  • 49
  • I can not solve this problem ... I'm trying all the solutions, but I do not get results ... Any other ideas? – kAiN Sep 16 '13 at 14:04
  • To start with I would move the `[self.searchResults removeAllObjects]` to the success block, right before you add the new entries (the `addObjectsFromArray:` call). – Timothy Walters Sep 16 '13 at 22:39
  • Timothy ... seems to work now! Do not crash! imagined must be a simple thing but I did not think so simple: (.. you had to move in the success block "remove all object" ... Currently, only one problem remained ... The search does not find names with a lowercase letter ... Ex: Member: Francesca Search Text: Francesca (found by the searchbar) francesca (not found by the search bar) How can I eliminate the distinction between upper and lower case? – kAiN Sep 16 '13 at 22:54
  • Parse doesn't support case-insensitive searches at this time. The common solution is to add another field where you copy the field(s) you want to search on, forcing the contents to lowercase. This can be done in your code or by adding some Cloud Code. While at it you can combine multiple fields into the search field to allow easy searching (e.g. FirstName and LastName). – Timothy Walters Sep 16 '13 at 23:00
  • Excellent! Thank so Very Mouch Timothy!!you have been very kind to help me! – kAiN Sep 16 '13 at 23:07
  • See http://stackoverflow.com/questions/18762881/search-for-case-insensitive-data-from-parse-using-java-script for more information. – Timothy Walters Sep 16 '13 at 23:11
  • Timothy know if there 's also something about how can I pass data from SearchDisplay Controll also in addition to the normal prepareForSegue already that I'm using? – kAiN Sep 17 '13 at 00:47
  • Please post another question, if you can't find what you want using a search. – Timothy Walters Sep 17 '13 at 01:46
  • I posted here as I've recommended: P Rory – kAiN Sep 17 '13 at 07:44