Search in Grouped UITableView

后端 未结 1 688
半阙折子戏
半阙折子戏 2020-12-04 04:08

I am new in Objective-C development, and I am trying to filter the content of a grouped UITableView.

This is what I did but still dosen\'t work :

-         


        
相关标签:
1条回答
  • 2020-12-04 04:52
    //
    //  ViewController.m
    //  SearchTut
    //
    
    
    #import "ViewController.h"
    #import "SearchTableCell.h"
    #import "XMLReader.h"
    
    @interface ViewController ()<UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate>
    
    @property (weak, nonatomic) IBOutlet UITableView *tablView;
    @property (weak, nonatomic) IBOutlet UISearchBar *searchBr;
    
    @property (nonatomic, strong) NSMutableArray *arrayList; //main table array
    @property (nonatomic, strong) NSMutableArray *arrayFilteredList; //array with search results while user types in search bar
    @property (nonatomic, strong) NSMutableDictionary *dictList; //need to manufacture an equivalent dictionary like below from the json array
    /*
     @{
         @"B" : @[@"Bear", @"Black Swan", @"Buffalo"],
         @"C" : @[@"Camel", @"Cockatoo"],
         @"D" : @[@"Dog", @"Donkey"],
         @"E" : @[@"Emu"],
         @"G" : @[@"Giraffe", @"Greater Rhea"],
         @"H" : @[@"Hippopotamus", @"Horse"],
         @"K" : @[@"Koala"],
         @"L" : @[@"Lion", @"Llama"],
         @"M" : @[@"Manatus", @"Meerkat"],
         @"P" : @[@"Panda", @"Peacock", @"Pig", @"Platypus", @"Polar Bear"],
         @"R" : @[@"Rhinoceros"],
         @"S" : @[@"Seagull"],
         @"T" : @[@"Tasmania Devil"],
         @"W" : @[@"Whale", @"Whale Shark", @"Wombat"]
     };
     Refer: https://www.appcoda.com/ios-programming-index-list-uitableview/
    */
    
    @property (nonatomic, strong) NSMutableDictionary *dictListFiltered; //dictionary when searched
    @property (nonatomic, assign) BOOL isFiltered; //If user starts entering text in search bar, this flag is YES. If there is no text in search bar, this flag is NO.
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Initialisers
        self.tablView.dataSource = self;
        self.tablView.delegate = self;
        self.searchBr.delegate = self;
        self.arrayList = [NSMutableArray array];
        self.dictList = [NSMutableDictionary dictionary];
        self.dictListFiltered = [NSMutableDictionary dictionary];
        self.isFiltered = NO;
    
        //Get and parse XML from file and load the result in array
        NSString *strXMLPath = [[NSBundle mainBundle] pathForResource:@"List" ofType:@"xml"];
        NSError *error;
        NSString *strXML = [NSString stringWithContentsOfFile:strXMLPath encoding:NSUTF8StringEncoding error:&error];
        NSDictionary *dict = [XMLReader dictionaryForXMLString:strXML error:&error];
        NSDictionary *dictPriceList = [dict objectForKey:@"PRICELIST"];
        NSArray *arrayLine = [dictPriceList objectForKey:@"LINE"];
        NSMutableArray *arrayTempPriceList = [NSMutableArray array];
        for (NSDictionary *dict in arrayLine) {
            [arrayTempPriceList addObject:dict];
        }
        self.arrayList = arrayTempPriceList;
        NSLog(@"%@", self.arrayList);
    
        //Create dictionary for sectioned table grouped with respect to PRICELISTCATEGORY value. PRICELISTCATEGORY value will be set in the section title. Logic to group table in sections is below
        [self groupXMLinSectionsWithArray:arrayTempPriceList];
    }
    
    - (void)groupXMLinSectionsWithArray:(NSMutableArray *)arrayJson {
        if (arrayJson.count > 0) { //added this condition to reset json during search.
            for (NSDictionary *dict in arrayJson ) {
                NSString *strPriceListCategory = [[dict objectForKey:@"PRICELISTCATEGORY"] objectForKey:@"text"];
                if (self.isFiltered) {
                    if ([[self.dictListFiltered allKeys] containsObject:strPriceListCategory]) {
                        NSMutableArray *arrayTemp = [self.dictListFiltered objectForKey:strPriceListCategory];
                        [arrayTemp addObject:dict];
                        [self.dictListFiltered setObject:arrayTemp forKey:strPriceListCategory];
                    } else {
                        NSMutableArray *arrayTemp = [[NSMutableArray alloc] initWithObjects:dict, nil];
                        [self.dictListFiltered setObject:arrayTemp forKey:strPriceListCategory];
                    }
                } else {
                    if ([[self.dictList allKeys] containsObject:strPriceListCategory]) {
                        NSMutableArray *arrayTemp = [self.dictList objectForKey:strPriceListCategory];
                        [arrayTemp addObject:dict];
                        [self.dictList setObject:arrayTemp forKey:strPriceListCategory];
                    } else {
                        NSMutableArray *arrayTemp = [[NSMutableArray alloc] initWithObjects:dict, nil];
                        [self.dictList setObject:arrayTemp forKey:strPriceListCategory];
                    }
                }
    
            }
        } else { //if search results yield no json array, then remove all objects from dictionary
            [self.dictList removeAllObjects];
            [self.dictListFiltered removeAllObjects];
        }
        [self.tablView reloadData];
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    #pragma mark - TableView Datasource
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        NSArray *arrayTemp = [NSArray array];
        if (self.isFiltered) {
            NSArray *arrayListAllKeys = [self.dictListFiltered allKeys];
            arrayTemp = [self.dictListFiltered objectForKey:[arrayListAllKeys objectAtIndex:section]];
        } else {
            NSArray *arrayListAllKeys = [self.dictList allKeys];
            arrayTemp = [self.dictList objectForKey:[arrayListAllKeys objectAtIndex:section]];
        }
        return [arrayTemp count];
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        SearchTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SearchTableCellId" forIndexPath:indexPath];
        NSDictionary *dict;
        if (self.isFiltered) {
            NSArray *arrayPriceListAllKeys = [self.dictListFiltered allKeys];
            NSArray *arrayPrice = [self.dictListFiltered objectForKey:[arrayPriceListAllKeys objectAtIndex:indexPath.section]];
            dict = [arrayPrice objectAtIndex:indexPath.row];
        } else {
            NSArray *arrayPriceListAllKeys = [self.dictList allKeys];
            NSArray *arrayPrice = [self.dictList objectForKey:[arrayPriceListAllKeys objectAtIndex:indexPath.section]];
            dict = [arrayPrice objectAtIndex:indexPath.row];
        }
        cell.lblBarCode.text = [[dict objectForKey:@"APNBARCODE"] objectForKey:@"text"];
        cell.lblPackDescription.text = [[dict objectForKey:@"PACKDESCRIPTION"] objectForKey:@"text"];
        cell.lblProduct.text = [[dict objectForKey:@"PRODUCT"] objectForKey:@"text"];
        cell.lblProductName.text = [[dict objectForKey:@"PRODUCTNAME"] objectForKey:@"text"];
    
        return cell;
    }
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        if (self.isFiltered) {
            return [[self.dictListFiltered allKeys] count];
        } else {
            return [[self.dictList allKeys] count];
        }
    }
    
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
        NSString *price = @"";
        if (self.isFiltered) {
            price = [[self.dictListFiltered allKeys] objectAtIndex:section];
        } else {
            price = [[self.dictList allKeys] objectAtIndex:section];
        }
        return price;
    }
    
    - (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
        return 50.0;
    }
    
    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
        NSString *sectionTitle = [self tableView:tableView titleForHeaderInSection:section];
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(8, 8, self.tablView.frame.size.width - 16, 30)];
        //If you add a bit to x and decrease y, it will be more in line with the tableView cell (that is in iPad and landscape)
        label.backgroundColor = [UIColor clearColor];
        label.textColor = [UIColor whiteColor];
        label.shadowColor = [UIColor whiteColor];
        label.shadowOffset = CGSizeMake(0.5, 0.5);
        label.font = [UIFont boldSystemFontOfSize:18];
        label.text = sectionTitle;
    
        // Create header view and add label as a subview
        UIView *viewHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tablView.frame.size.width, 50)];
        viewHeader.backgroundColor = [UIColor colorWithRed:0.4 green:0.4 blue:0.4 alpha:1];
        [viewHeader addSubview:label];
        return viewHeader;
    }
    
    #pragma mark - SearchBar Delegates
    
    - (void)updateSearchResults
    {
        //You can use the below commented code in case you need an exact match of the PRODUCT value text you entered in search bar
        /*
         NSMutableArray *searchResults = [self.arrayList mutableCopy];
         NSString *strippedString = [searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
         NSPredicate *predicate = [NSPredicate predicateWithFormat:@"PRODUCT.text==[c] %@", strippedString];
         searchResults = [[searchResults filteredArrayUsingPredicate:predicate] mutableCopy];
         // hand over the filtered results to our search results table
         self.arrayFilteredList = searchResults;
         //NSLog(@"%@", self.arrayFilteredPriceList);
         [self groupXMLinSectionsWithArray:self.arrayFilteredList];
         */
    
    
        //Below code searches depending on Product / Product Name / APNBarCode values
        NSString *searchText = self.searchBr.text;
        NSMutableArray *searchResults = [self.arrayList mutableCopy];
        NSString *strippedString = [searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        NSArray *searchItems = nil;
        if (strippedString.length > 0) {
            searchItems = [strippedString componentsSeparatedByString:@" "];
        }
    
        NSMutableArray *andMatchPredicates = [NSMutableArray array];
    
        for (NSString *searchString in searchItems) {
            NSMutableArray *searchItemsPredicate = [NSMutableArray array];
    
            // Below we use NSExpression represent expressions in our predicates.
            // NSPredicate is made up of smaller, atomic parts: two NSExpressions (a left-hand value and a right-hand value)
    
            // Product
            NSExpression *lhsProduct = [NSExpression expressionForKeyPath:@"PRODUCT.text"];
            NSExpression *rhsProduct = [NSExpression expressionForConstantValue:searchString];
            NSPredicate *finalPredicateProduct = [NSComparisonPredicate
                                                  predicateWithLeftExpression:lhsProduct
                                                  rightExpression:rhsProduct
                                                  modifier:NSDirectPredicateModifier
                                                  type:NSContainsPredicateOperatorType
                                                  options:NSCaseInsensitivePredicateOption];
            [searchItemsPredicate addObject:finalPredicateProduct];
    
            // Product Name
            NSExpression *lhsProductName = [NSExpression expressionForKeyPath:@"PRODUCTNAME.text"];
            NSExpression *rhsProductName = [NSExpression expressionForConstantValue:searchString];
            NSPredicate *finalPredicateProductName = [NSComparisonPredicate
                                                      predicateWithLeftExpression:lhsProductName
                                                      rightExpression:rhsProductName
                                                      modifier:NSDirectPredicateModifier
                                                      type:NSContainsPredicateOperatorType
                                                      options:NSCaseInsensitivePredicateOption];
            [searchItemsPredicate addObject:finalPredicateProductName];
    
    
            // APN Bar Code
            NSExpression *lhsAPNBarCode = [NSExpression expressionForKeyPath:@"APNBARCODE.text"];
            NSExpression *rhsAPNBarCode = [NSExpression expressionForConstantValue:searchString];
            NSPredicate *finalPredicateAPNBarCode= [NSComparisonPredicate
                                                    predicateWithLeftExpression:lhsAPNBarCode
                                                    rightExpression:rhsAPNBarCode
                                                    modifier:NSDirectPredicateModifier
                                                    type:NSContainsPredicateOperatorType
                                                    options:NSCaseInsensitivePredicateOption];
            [searchItemsPredicate addObject:finalPredicateAPNBarCode];
    
            // AVERAGECOST
            NSExpression *lhsPACKDESCRIPTION = [NSExpression expressionForKeyPath:@"PACKDESCRIPTION.text"];
            NSExpression *rhsPACKDESCRIPTION = [NSExpression expressionForConstantValue:searchString];
            NSPredicate *finalPredicatePACKDESCRIPTIONt = [NSComparisonPredicate
                                                    predicateWithLeftExpression:lhsPACKDESCRIPTION
                                                    rightExpression:rhsPACKDESCRIPTION
                                                    modifier:NSDirectPredicateModifier
                                                    type:NSContainsPredicateOperatorType
                                                    options:NSCaseInsensitivePredicateOption];
            [searchItemsPredicate addObject:finalPredicatePACKDESCRIPTIONt];
    
            // at this OR predicate to our master AND predicate
            NSCompoundPredicate *orMatchPredicates = [NSCompoundPredicate orPredicateWithSubpredicates:searchItemsPredicate];
            [andMatchPredicates addObject:orMatchPredicates];
    
        }
    
        // match up the fields of the Product object
        NSCompoundPredicate *finalCompoundPredicate =
        [NSCompoundPredicate andPredicateWithSubpredicates:andMatchPredicates];
        searchResults = [[searchResults filteredArrayUsingPredicate:finalCompoundPredicate] mutableCopy];
        // hand over the filtered results to our search results table
        self.arrayFilteredList = searchResults;
        //NSLog(@"%@", self.arrayFilteredPriceList);
    
        [self groupXMLinSectionsWithArray:self.arrayFilteredList];
    }
    
    //This method gets called when user starts entering text in search bar
    - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
        if (searchText.length == 0) {
            self.isFiltered = NO;
            [self.dictList removeAllObjects];
            [self groupXMLinSectionsWithArray:self.arrayList];
            [self.tablView reloadData];
        } else {
            self.isFiltered = YES;
            self.arrayFilteredList = [NSMutableArray new];
            [self.dictListFiltered removeAllObjects];
            [self updateSearchResults];
        }
    }
    
    - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
        [searchBar resignFirstResponder];
        [self.dictList removeAllObjects];
        [self groupXMLinSectionsWithArray:self.arrayList];
        [self.tablView reloadData];
    }
    
    - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
        [searchBar resignFirstResponder];
        [self.tablView reloadData];
    }
    
    
    @end
    

    Above code logic is based on the json with dictionaries contained in an array and we create sections depending on PRICELISTCATEGORY value

     [
        { 
           "PRODUCT": {
              "text": "GELDCMFRAME"
           },
           "PRODUCTMAJORGROUP": {
              "text": "IC"
           },
           "PRICELISTCATEGORY": {
              "text": "GELDISP"
           },
           "APNBARCODE": {
              "text": "931000"
           },
           "PACKDESCRIPTION": {
              "text": "Some Description"
           },
           "PRODUCTNAME": {
              "text": "Description"
           }
           and so on
        }, and so on
     ]
    

    Refer screenshot below for search results

    0 讨论(0)
提交回复
热议问题