简体   繁体   中英

SearchDisplayController search multiple arrays

Currently I'm populating my tableviewcells with the contents of multiple arrays representing a name, id, etc.

My question comes when I start to use the search display controller. I have an array with a list of names, a list of IDs, a list of barcodes, and a list of Aliases. When the user types in the search bar I need to be able to search all 4 arrays. When it finds the result in 1 array it has to pair the result with the 3 other arrays..

Example

  1. Names (apple,carrot,banana, dog)
  2. alias (red, orange, yellow, brown)
  3. barcode (1,2,10,20)
  4. id (30, 40, 50, 60)

So if the user types "a" I should populate the table view with Apple, Carrot, Banana and the associated alias, barcode, id.

If the user were to type 2 I should only get carrot and dog.

If the user were to type 0 I would get all of those items.

Any ideas how to accomplish this?

UPDATE: This is how I did it.

    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {

    BOOL shouldReturn = FALSE;
    [searchResults removeAllObjects];

    for (int i = 0; i < [itemIDRows count]; i++) {

        BOOL foundResult = FALSE;

        if ([[itemIDRows objectAtIndex:i] rangeOfString:searchString].location != NSNotFound) {
            foundResult = TRUE;
        }
        if ([[nameRows objectAtIndex:i] rangeOfString:searchString].location != NSNotFound) {
            foundResult = TRUE;
        }
        if ([[barcodeRows objectAtIndex:i] rangeOfString:searchString].location != NSNotFound) {
            foundResult = TRUE;
        }
        if ([[aliasRows objectAtIndex:i] rangeOfString:searchString].location != NSNotFound) {
            foundResult = TRUE;
        }
        if (foundResult) {
            NSNumber *result = [NSNumber numberWithInt:i];
            if ([self searchResults] == nil) {
                NSMutableArray *array = [[NSMutableArray alloc] init];
                [self setSearchResults:array];
                [array release];
            }
            [searchResults addObject:result];
            shouldReturn = YES;
        }
    }
    return shouldReturn;    
}

Then when I'm populating the tableview I do something like this

if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]) { 
    [cell setCellContentsName:[NSString stringWithFormat:@"%@", [nameRows objectAtIndex:[[searchResults objectAtIndex:indexPath.row] integerValue]]];  
} else {
    [cell setCellContentsName:[NSString stringWithFormat:@"%@", [nameRows objectAtIndex:indexPath.row]];
}

However when I type something like 9999 it brings up instances where only 1 9 is in the ID or barcode. Any ideas how to fix that?

UPDATE2: Solved the problem by having the list always refresh instead of only reloading the data if a result was found. Now it works perfectly :D

The search display controller calls the

  UISearchDisplayDelegate 

method:

 searchDisplayController:shouldReloadTableForSearchString:

Inside this method, you need to implement your logic. This logic will need to search all 4 of your arrays for hits, and do the appropriate lookups (ie to get from orange to carrot, or from 50 to banana). Each time you get a hit, I would put it in an NSMutableSet (to prevent dupes). Then when you're done searching all arrays, copy the set into the array that your table's data source reads from.

If you want to show the user WHY a given row is a hit (ie they typed 50 and got banana), you'd have to display all 4 of the attributes in your table cell. And you'd need to highlight the part that matched. If you do this, I'd create a small container class, something like "searchHit" that contains all 4 attributes, as well as a flag for which attribute got the hit, and possibly the substring of the attribute that got the hit (so you can use a yellow background for this substring, for example.) The tableView's data source would then have an array of these searchHit objects to display, and your cellForRowAtIndexPath would need to decode this object and display the hit appropriately.

You can do that with NSPredicate using KVC object.

Create an NSObject respond to the KVC scheme http://theocacao.com/document.page/161 . You can use property for that.

Filter your array with an NSPredicate http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/Reference/NSPredicate.html

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self.name LIKE[cd] %@ OR self.alias LIKE[cd] %@",searchString,searchString];
NSArray *result = [baseArray filteredArrayUsingPredicate:predicate];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM