0

I have added search bar for collection view using programatically .But when i enter the names to search nothing shows.I have some section also and each section contains some data.

Here is my code:

@interface ViewController ()
{
   NSMutableArray *arrayPDFName;
    NSMutableArray *titleArray;


}


@property (nonatomic,strong) NSArray        *dataSourceForSearchResult;
@property (nonatomic)        BOOL           searchBarActive;
@property (nonatomic)        float          searchBarBoundsY;

@property (nonatomic,strong) UISearchBar        *searchBar;
@property (nonatomic,strong) UIRefreshControl   *refreshControl;

@end


@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.dataSourceForSearchResult = [NSArray new];
     titleArray = [NSMutableArray array];
    [self getdata];


    self.mycollectionView.dataSource = self;
    self.mycollectionView.delegate = self;
   [self.mycollectionView reloadData];


 }

-(NSString*)sha256HashFor:(NSString*)input
{
    const char* str = [input UTF8String];
    unsigned char result[CC_SHA256_DIGEST_LENGTH];
    CC_SHA256(str, strlen(str), result);

    NSMutableString *ret = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2];
    for(int i = 0; i<CC_SHA256_DIGEST_LENGTH; i++)
    {
        [ret appendFormat:@"%02x",result[i]];
    }
    return ret;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];

}


-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self prepareUI];
}


-(void)getdata {

    NSString *userName = @“username@yahoo.com";
    NSString *password = @“password”;
    NSData *plainData = [password dataUsingEncoding:NSUTF8StringEncoding];
    NSString *base64String = [plainData base64EncodedStringWithOptions:0];
    base64String=[self sha256HashFor: base64String];

    NSString *urlString = @"https://api.exampleport/user/orderid/files";

    NSMutableURLRequest *request= [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:urlString]];
    [request setHTTPMethod:@"GET"];


    // basic authendication
    NSString *authStr = [NSString stringWithFormat:@"%@:%@", userName, base64String];
    NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
    //header-field
    NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64Encoding]];
    [request setValue:authValue forHTTPHeaderField:@"Authorization"];

    NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];

    NSString *str = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];


    NSError * error;

    self->arrayPDFName = [[NSMutableArray alloc]init];
    NSDictionary *jsonResults = [NSJSONSerialization JSONObjectWithData:returnData options:NSJSONReadingMutableContainers error:nil];




    NSDictionary *dictOriginal = jsonResults[@“dark”];
    [titleArray addObject:[NSString stringWithFormat:@"dark(%@)”, dictOriginal[@"count"]]];


    NSDictionary *dictOriginal2 = jsonResults[@"orange”];
    [titleArray addObject:[NSString stringWithFormat:@"orange(%@)”, dictOriginal2[@"count"]]];



    NSDictionary *dictOriginal3 = jsonResults[@"pencill”];
    [titleArray addObject:[NSString stringWithFormat:@"pencill(%@)”, dictOriginal3[@"count"]]];


     NSDictionary *dictOriginal4 = jsonResults[@"smart”];
    [titleArray addObject:[NSString stringWithFormat:@"smart(%@)”, dictOriginal4[@"count"]]];


    NSArray *arrayFiles = [NSArray arrayWithObjects: dictOriginal, dictOriginal2, dictOriginal3, dictOriginal4, nil];


     NSLog(@"str: %@", titleArray);

        for (NSDictionary *dict in arrayFiles) {
        NSMutableArray *arr = [NSMutableArray array];

        NSArray *a = dict[@"files"];
        for(int i=0; i < a.count; i ++) {


            NSString *strName = [NSString stringWithFormat:@"%@",[[dict[@"files"] objectAtIndex:i] valueForKey:@"name"]];
           // NSLog(@"str: %@", strName);
            [arr addObject:strName];
        }
        [arrayPDFName addObject:arr];
    }




    //Get plist path
    NSString *errorDesc;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory1 = [paths objectAtIndex:0];
    NSString *plistPath = [documentsDirectory1 stringByAppendingPathComponent:@"SampleData.plist"];
   //NSLog(@"plistPath : %@",plistPath);

    //Save data from json to plist
    NSString *error1;
    returnData  = [NSPropertyListSerialization dataFromPropertyList:jsonResults
                                                      format:NSPropertyListXMLFormat_v1_0
                                            errorDescription:&error];
    if(returnData ) {
        if ([returnData  writeToFile:plistPath atomically:YES]) {
            NSLog(@"Data successfully saved.");
        }else {
            NSLog(@"Did not managed to save NSData.");
        }
    }
    else {
        NSLog(@"%@",errorDesc);
    }

   // NSArray *stringsArray = [NSArray arrayWithContentsOfFile:plistPath];

    NSDictionary *stringsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
   // NSLog(@"str: %@", stringsDictionary);
}
//delegate method for header



-(UICollectionReusableView*) collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {


    HeaderView * header = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"myHeader" forIndexPath:indexPath];


    header.myHeaderLabel.text = titleArray[indexPath.section];

    return header;




}



#pragma mark - UICollectionView Datasource

-(NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView {



   return titleArray.count;
}



-(NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {


    if (self.searchBarActive) {
        return self.dataSourceForSearchResult.count;
    }

    NSArray *a = arrayPDFName[section];
    if (a.count == 0)

    {


        return 1;


    }
        else


        {            
        return a.count;
            }


    }
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section {
    return CGSizeMake(0, 80);
}   



- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath: (NSIndexPath *)indexPath {
    VenueCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@"mycell" forIndexPath:indexPath];
    cell.backgroundColor = [UIColor whiteColor];
    cell.imgV.image = [UIImage imageNamed:@"doc1.png"];

    if (self.searchBarActive) {
        cell.myLabel.text = _dataSourceForSearchResult[indexPath.section][indexPath.row];
    }else{
        NSArray *a = arrayPDFName[indexPath.section];
        if (a.count == 0) {

           cell.myLabel.text = @"NO DATA";

       return cell;

        }


        cell.myLabel.text = a[indexPath.row];
    }


    return cell; 
}

//////////////////////////for search bar  //////////

#pragma mark - actions
-(void)refreashControlAction{
    [self cancelSearching];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        // stop refreshing after 2 seconds
        [self.mycollectionView reloadData];
        [self.refreshControl endRefreshing];
    });
}



#pragma mark - search
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{
    NSPredicate *resultPredicate    = [NSPredicate predicateWithFormat:@"self contains[c] %@", searchText];
    self.dataSourceForSearchResult  = [self->arrayPDFName filteredArrayUsingPredicate:resultPredicate];
}

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
    // user did type something, check our datasource for text that looks the same
    if (searchText.length>0) {
        // search and reload data source
        self.searchBarActive = YES;
        [self filterContentForSearchText:searchText
                                   scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
                                          objectAtIndex:[self.searchDisplayController.searchBar
                                                         selectedScopeButtonIndex]]];
        [self.mycollectionView reloadData];
    }else{
        // if text lenght == 0
        // we will consider the searchbar is not active
        self.searchBarActive = NO;
    }
}

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{
    [self cancelSearching];
    [self.mycollectionView reloadData];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
    self.searchBarActive = YES;
    [self.view endEditing:YES];
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
    // we used here to set self.searchBarActive = YES
    // but we'll not do that any more... it made problems
    // it's better to set self.searchBarActive = YES when user typed something
    [self.searchBar setShowsCancelButton:YES animated:YES];
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar{
    // this method is being called when search btn in the keyboard tapped
    // we set searchBarActive = NO
    // but no need to reloadCollectionView
    self.searchBarActive = NO;
    [self.searchBar setShowsCancelButton:NO animated:YES];
}
-(void)cancelSearching{
    self.searchBarActive = NO;
    [self.searchBar resignFirstResponder];
    self.searchBar.text  = @"";
}
#pragma mark - prepareVC
-(void)prepareUI{
    [self addSearchBar];
    [self addRefreshControl];
}
-(void)addSearchBar{
    if (!self.searchBar) {
        self.searchBarBoundsY = self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height;
        self.searchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0,self.searchBarBoundsY, [UIScreen mainScreen].bounds.size.width, 50)];
        self.searchBar.searchBarStyle       = UISearchBarStyleMinimal;
        self.searchBar.tintColor            = [UIColor whiteColor];
        self.searchBar.barTintColor         = [UIColor whiteColor];
        self.searchBar.delegate             = self;
        self.searchBar.placeholder          = @"Search here";

        [[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setTextColor:[UIColor whiteColor]];

        // add KVO observer.. so we will be informed when user scroll colllectionView
        [self addObservers];
    }

    if (![self.searchBar isDescendantOfView:self.view]) {
        [self.view addSubview:self.searchBar];
    }
}

-(void)addRefreshControl{
    if (!self.refreshControl) {
        self.refreshControl                  = [UIRefreshControl new];
        self.refreshControl.tintColor        = [UIColor whiteColor];
        [self.refreshControl addTarget:self
                                action:@selector(refreashControlAction)
                      forControlEvents:UIControlEventValueChanged];
    }
    if (![self.refreshControl isDescendantOfView:self.mycollectionView]) {
        [self.mycollectionView addSubview:self.refreshControl];
    }
}
-(void)startRefreshControl{
    if (!self.refreshControl.refreshing) {
        [self.refreshControl beginRefreshing];
    }
}

Where i am doing mistake and what i need to change to work.Thanks in advance!

user5513630
  • 1,709
  • 8
  • 24
  • 48
  • Have you checked that `self.dataSourceForSearchResult` is ever populated? – Avi Nov 03 '15 at 17:59
  • first my code worked well.I also checked . and i have change my main array "arrayPDFName" with some changed with section.so after that when i search not able to see the searched items – user5513630 Nov 03 '15 at 18:05
  • Why are you using `self->`? – trojanfoe Nov 03 '15 at 18:37
  • i din't set @property for my arrayPDFNmae. So when i use self.arrayPDFName... --It came up with waring to change with that arrow symbol – user5513630 Nov 03 '15 at 18:44
  • @user5513630 Your `arrayPDFName` having array as object. So you have to use SUBQUERY in predicate. Please refer here, http://stackoverflow.com/questions/3810992/quick-explanation-of-subquery-in-nspredicate-expression – Vijay Nov 04 '15 at 05:52
  • @vijay really dint make sense bro.. – user5513630 Nov 04 '15 at 05:55
  • does i need to add any line like they said in that link you gave – user5513630 Nov 04 '15 at 05:56
  • yes. You need to change the predicate format because your `arrayPDFName` have 4 array object. Each array object have string object. – Vijay Nov 04 '15 at 05:58
  • so i need to change format at here uh bro - `- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{ NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"self contains[c] %@", searchText]; self.dataSourceForSearchResult = [self->arrayPDFName filteredArrayUsingPredicate:resultPredicate]; }` – user5513630 Nov 04 '15 at 06:01
  • Yes exactly. Do the changes in that place – Vijay Nov 04 '15 at 06:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/94154/discussion-between-user5513630-and-vijay). – user5513630 Nov 04 '15 at 06:23
  • bro i have found that code, but dont know how to change the format – user5513630 Nov 04 '15 at 06:24
  • i have changed, but when i enter first letter in search field,app getting crash `- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{ NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(SELF, $a, $a.@count > 42)", searchText]; self.dataSourceForSearchResult = [self->arrayPDFName filteredArrayUsingPredicate:resultPredicate]; } ` – user5513630 Nov 04 '15 at 06:30
  • @vijay it getting crash bro – user5513630 Nov 04 '15 at 06:55
  • @user5513630, check my answer. – Vijay Nov 04 '15 at 07:33

1 Answers1

3

It seems your arrayPDFName have array object and each array object have string object. There are two ways to filter you array.

Way - 1

If you want to get the list of array which has the search string the use SUBQUERY with your predicate. Like below.

NSArray *a1 = @[@"a1", @"a2", @"a3"];
NSArray *a2 = @[@"a1", @"a2", @"a3"];
NSArray *a3 = @[@"a1", @"a2", @"a3"];
NSArray *a4 = @[@"a2", @"a3"];

NSArray *allA = @[a1, a2, a3, a4];

NSPredicate *pre = [NSPredicate predicateWithFormat:@"SUBQUERY(SELF, $a, $a == %@).@count > 0", @"a1"];
NSArray *a = [allA filteredArrayUsingPredicate:pre];

Way - 2

If you want to get the search string alone from each array object then follow the below,

NSMutableArray *fa = [[NSMutableArray alloc] init];
for (NSArray *a in allA) {
    NSPredicate *p = [NSPredicate predicateWithFormat:@"self CONTAINS[c] %@", @"a3"];
    [fa addObjectsFromArray:[a filteredArrayUsingPredicate:p]];
}

Note: Above code done with same sample data. Replace it as you want.

As per your code replace the below code

-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
    NSMutableArray *fa = [[NSMutableArray alloc] init];
    for (NSArray *a in arrayPDFName) {
        NSPredicate *p = [NSPredicate predicateWithFormat:@"self CONTAINS[c] %@", searchText];
        [fa addObjectsFromArray:[a filteredArrayUsingPredicate:p]];
    }
    self.dataSourceForSearchResult = [NSArray arrayWithArray:fa];
}

-(NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView { 
  if(self.searchBarActive) 
    return 1; 
  return titleArray.count; 
}

In cellForItemAtIndexPath

cell.myLabel.text = _dataSourceForSearchResult[indexPath.row];
Vijay
  • 791
  • 1
  • 8
  • 23
  • in your 1 st way you have said @"a1" - is it correct or @"allA" – user5513630 Nov 04 '15 at 07:57
  • 1st way--------- `- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{ NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(SELF, $a, $a == %@).@count > 0", searchText]; self.dataSourceForSearchResult = [self->arrayPDFName filteredArrayUsingPredicate:resultPredicate]; }`---din't get the search data – user5513630 Nov 04 '15 at 08:06
  • 2nd way-- `- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{ NSMutableArray *fa = [[NSMutableArray alloc] init]; for (NSArray *a in arrayPDFName) { NSPredicate *p = [NSPredicate predicateWithFormat:@"self CONTAINS[c] %@", @"arrayPDFName"]; [fa addObjectsFromArray:[a filteredArrayUsingPredicate:p]]; } }` Not able to get the searched data – user5513630 Nov 04 '15 at 08:08
  • What you have in `fa` array? I've tested my code it is working fine. – Vijay Nov 04 '15 at 08:20
  • bro, i have replace `fa` with `arrayPDFName` because it only having my all array object – user5513630 Nov 04 '15 at 08:33
  • see this --`- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{ NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(SELF, $a, $a == %@).@count > 0", @"arrayPDFName"]; self.dataSourceForSearchResult = [self->arrayPDFName filteredArrayUsingPredicate:resultPredicate]; }` – user5513630 Nov 04 '15 at 08:46
  • this alos i have changes but not able to get search data – user5513630 Nov 04 '15 at 08:46
  • And what this `@"a1"];` in way 1 AND `@"self CONTAINS[c] %@", @"a3"];` in this what is `@"a3"` – user5513630 Nov 04 '15 at 08:57
  • also if i change the code as you have ,does i need to change anything in my `cellForItemAtIndexPath` – user5513630 Nov 04 '15 at 09:12
  • @user5513630 Edited my answer. Do that as it is. You don't need to change anything and anywhere. – Vijay Nov 04 '15 at 10:00
  • i did but app crash `reason: '-[__NSCFString objectAtIndexedSubscript:]: unrecognized selector sent to instance 0xb236740'` – user5513630 Nov 04 '15 at 10:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/94187/discussion-between-vijay-and-user5513630). – Vijay Nov 04 '15 at 10:19