Search code examples
searchxlform

How to use XLData search with a specified list of data


EDIT: After fiddling around some more, I realised that using XLData required me to have the data somewhere online, because the search requested the results from a URL instead of from my dataset.

So, now my question is, how do I use XLData's search functionality with a specific list of data and query that data set instead of some data online?

Just an afterthought - Typing "a" did return some results when applied as the code below. So how did that happen?


I'm using XLData to load a list of customers to search and select from, but search results entered into the search box doesn't seem to affect the search results at all.

For example, searching for "food" (when the first list item clearly has "food" in it's name), doesn't filter that customer name to the search results. And searching for numbers - a customer name starting with a digit - gives no results.

How do I catch the search results based on search terms to debug it and see what's going on?

Another thing is that when the search results load, the list is truncated to 9 items, even though there are like over 1000 customers.

enter image description here

This is the class for selecting a customer (some user name and image code is still in there for line items, because I used XLData's example as is, but I don't display an image):

#import "CustomersTableViewController.h"
#import "AppDelegate.h"
#import "HTTPSessionManager.h"
#import <AFNetworking/UIImageView+AFNetworking.h>

@interface UserCell : UITableViewCell

@property (nonatomic) UIImageView * userImage;
@property (nonatomic) UILabel * userName;

@end

@implementation UserCell

@synthesize userImage = _userImage;
@synthesize userName  = _userName;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code

        [self.contentView addSubview:self.userImage];
        [self.contentView addSubview:self.userName];

        [self.contentView addConstraints:[self layoutConstraints]];
    }
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];
}

#pragma mark - Views

-(UIImageView *)userImage
{
    if (_userImage) return _userImage;
    _userImage = [UIImageView new];
    [_userImage setTranslatesAutoresizingMaskIntoConstraints:NO];
    _userImage.layer.masksToBounds = YES;
    _userImage.layer.cornerRadius = 10.0f;
    return _userImage;
}

-(UILabel *)userName
{
    if (_userName) return _userName;
    _userName = [UILabel new];
    [_userName setTranslatesAutoresizingMaskIntoConstraints:NO];
    _userName.font = [UIFont fontWithName:@"HelveticaNeue" size:15.f];

    return _userName;
}

#pragma mark - Layout Constraints

-(NSArray *)layoutConstraints{

    NSMutableArray * result = [NSMutableArray array];

    NSDictionary * views = @{ @"image": self.userImage,
                              @"name": self.userName};

    NSDictionary *metrics = @{@"imgSize":@0.0,
                              @"margin" :@10.0};

    [result addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(margin)-[image(imgSize)]-[name]"
                                                                        options:NSLayoutFormatAlignAllTop
                                                                        metrics:metrics
                                                                          views:views]];

    [result addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(margin)-[image(imgSize)]"
                                                                        options:0
                                                                        metrics:metrics
                                                                          views:views]];

    return result;
}

@end


@interface CustomersTableViewController () <UISearchControllerDelegate>

@property (nonatomic, readonly) CustomersTableViewController * searchResultController;
@property (nonatomic, readonly) UISearchController * searchController;

@end

@implementation CustomersTableViewController
@synthesize rowDescriptor = _rowDescriptor;
@synthesize popoverController = __popoverController;
@synthesize searchController = _searchController;
@synthesize searchResultController = _searchResultController;

static NSString *const kCellIdentifier = @"CellIdentifier";
NSMutableArray *customers;

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        [self initialize];
    }
    return self;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if(self)
    {
        [self initialize];
    }

    return self;
}

- (void)initialize
{

    customers = [[NSMutableArray alloc] init];
    customers = [AppDelegate getCustomers];

    for (int i=0; i<[customers count]; i++){
        [self.dataStore addDataItem:[customers objectAtIndex:i]];
    }

    self.dataLoader =  [[XLDataLoader alloc] initWithURLString:@"/mobile/users.json" offsetParamName:@"offset" limitParamName:@"limit" searchStringParamName:@"filter"];
    self.dataLoader.delegate = self;
    self.dataLoader.storeDelegate = self;
    self.dataLoader.limit = [customers count];
    self.dataLoader.collectionKeyPath = @"";
}

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.tableView registerClass:[UserCell class] forCellReuseIdentifier:kCellIdentifier];
    self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];

    if (!self.isSearchResultsController){
        self.tableView.tableHeaderView = self.searchController.searchBar;
    }
    else{
        [self.tableView setContentInset:UIEdgeInsetsMake(64, 0, 0, 0)];
        [self.tableView setScrollIndicatorInsets:self.tableView.contentInset];
    }
}

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.searchController.searchBar sizeToFit];
}

#pragma mark - UITableViewDataSource

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UserCell *cell = (UserCell *) [tableView dequeueReusableCellWithIdentifier:kCellIdentifier forIndexPath:indexPath];;

    cell.userName.text = [customers objectAtIndex:indexPath.row];

    cell.accessoryType = [self.rowDescriptor.value isEqual:[customers objectAtIndex:indexPath.row]] ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;

    return cell;
}

#pragma mark - UITableViewDelegate

- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 44.0f;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    self.rowDescriptor.value = [customers objectAtIndex:indexPath.row];

    if (self.popoverController){
        [self.popoverController dismissPopoverAnimated:YES];
        [self.popoverController.delegate popoverControllerDidDismissPopover:self.popoverController];
    }
    else if ([self.parentViewController isKindOfClass:[UINavigationController class]]){
        [self.navigationController popViewControllerAnimated:YES];
    }
}

#pragma mark - XLDataLoaderDelegate

-(AFHTTPSessionManager *)sessionManagerForDataLoader:(XLDataLoader *)dataLoader
{
    return [HTTPSessionManager sharedClient];
}

#pragma mark - UISearchController

-(UISearchController *)searchController
{
    if (_searchController) return _searchController;

    self.definesPresentationContext = YES;
    _searchController = [[UISearchController alloc] initWithSearchResultsController:self.searchResultController];
    _searchController.delegate = self;
    _searchController.searchResultsUpdater = self.searchResultController;
    _searchController.searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    [_searchController.searchBar sizeToFit];
    return _searchController;
}


-(CustomersTableViewController *)searchResultController
{
    if (_searchResultController) return _searchResultController;
    _searchResultController = [self.storyboard instantiateViewControllerWithIdentifier:@"CustomersTableViewController"];
    _searchResultController.dataLoader.limit = 0; // no paging in search result
    _searchResultController.isSearchResultsController = YES;
    return _searchResultController;
}

@end

Solution

  • I ended up using a normal Search bar solution as described by Appcoda: http://www.appcoda.com/search-bar-tutorial-ios7/

    I'd still like to be able to use XLData as it helps with a lot of other things and seamlessly integrates with XLForms which I'm also using.

    But the search bar implementation from Appcoda ended up being sufficient for my requirements.