Search code examples
iosparse-platformparse-framework

Parse Framework iOS: Query for header by date


Scenario

I have an app that allows users to post suggestions onto a PFQueryTableViewController. I am using the parse.com framework and each post is created with an attached "date" 00/00/00 and "time" 00:00PM.

What I Need

To have sections in the tableview set up for each day ("date" object on the Post) - With the 00/00/00 displayed as the title for the section.

Question

Does anyone know how to design something like this?


Solution

  • There was something posted on the old parse.com forums for something similar to this:

    https://parse.com/questions/using-pfquerytableviewcontroller-for-uitableview-sections

    It is for sports, but you can easily modify it to match your needs.

    Here is the code if the link dies:

    SectionedQueryTableViewController.h

    @interface SectionedQueryTableViewController : PFQueryTableViewController
    
    @end
    

    SectionedQueryTableViewController.m

    #import "SectionedQueryTableViewController.h"
    
    @interface SectionedQueryTableViewController()
    @property (nonatomic, retain) NSMutableDictionary *sections;
    @property (nonatomic, retain) NSMutableDictionary *sectionToSportTypeMap;
    @end
    
    @implementation SectionedQueryTableViewController
    @synthesize sections = _sections;
    @synthesize sectionToSportTypeMap = _sectionToSportTypeMap;
    
    - (id)initWithStyle:(UITableViewStyle)style {
        self = [super initWithStyle:style];
        if (self) {
            self.className = @"Athlete";
            self.textKey = @"name";
            self.pullToRefreshEnabled = YES;
            self.paginationEnabled = YES;
            self.objectsPerPage = 25;
            self.sections = [NSMutableDictionary dictionary];
            self.sectionToSportTypeMap = [NSMutableDictionary dictionary];
        }
        return self;
    }
    
    
    #pragma mark - PFQueryTableViewController
    
    - (void)objectsDidLoad:(NSError *)error {
        [super objectsDidLoad:error];
    
        // This method is called every time objects are loaded from Parse via the PFQuery
    
        [self.sections removeAllObjects];
        [self.sectionToSportTypeMap removeAllObjects];
    
        NSInteger section = 0;
        NSInteger rowIndex = 0;
        for (PFObject *object in self.objects) {
            NSString *sportType = [object objectForKey:@"sportType"];
            NSMutableArray *objectsInSection = [self.sections objectForKey:sportType];
            if (!objectsInSection) {
                objectsInSection = [NSMutableArray array];
    
                // this is the first time we see this sportType - increment the section index
                [self.sectionToSportTypeMap setObject:sportType forKey:[NSNumber numberWithInt:section++]];
            }
    
            [objectsInSection addObject:[NSNumber numberWithInt:rowIndex++]];
            [self.sections setObject:objectsInSection forKey:sportType];
        }
    }
    
    - (PFQuery *)queryForTable {
        PFQuery *query = [PFQuery queryWithClassName:self.className];
    
        // If Pull To Refresh is enabled, query against the network by default.
        if (self.pullToRefreshEnabled) {
            query.cachePolicy = kPFCachePolicyNetworkOnly;
        }
    
        // If no objects are loaded in memory, we look to the cache first to fill the table
        // and then subsequently do a query against the network.
        if (self.objects.count == 0) {
            query.cachePolicy = kPFCachePolicyCacheThenNetwork;
        }
    
        // Order by sport type
        [query orderByAscending:@"sportType"];
        return query;
    }
    
    - (PFObject *)objectAtIndexPath:(NSIndexPath *)indexPath {
        NSString *sportType = [self sportTypeForSection:indexPath.section];
        NSArray *rowIndecesInSection = [self.sections objectForKey:sportType];
        NSNumber *rowIndex = [rowIndecesInSection objectAtIndex:indexPath.row];
        return [self.objects objectAtIndex:[rowIndex intValue]];
    }
    
    #pragma mark - UITableViewDataSource
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return self.sections.allKeys.count;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        NSString *sportType = [self sportTypeForSection:section];
        NSArray *rowIndecesInSection = [self.sections objectForKey:sportType];
        return rowIndecesInSection.count;
    }
    
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
        NSString *sportType = [self sportTypeForSection:section];
        return sportType;
    }
    
    
    #pragma mark - UITableViewDelegate
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        [super tableView:tableView didSelectRowAtIndexPath:indexPath];
    
        PFObject *selectedObject = [self objectAtIndexPath:indexPath];
    }
    
    
    #pragma mark - ()
    
    - (NSString *)sportTypeForSection:(NSInteger)section {
        return [self.sectionToSportTypeMap objectForKey:[NSNumber numberWithInt:section]];
    }
    
    @end