4

I've retrieved data from 2 different shared Google Calendars, and stored the data in an array. I need to sort the data into a sectioned UITableView, sorted by date.

Heres my code:

CalendarModel.h

#import "JSONModel.h"
#import "Time.h"

@interface CalendarModel : JSONModel

@property (strong, nonatomic) NSString* title;
@property (strong, nonatomic) NSArray<Time>* time;

@end

CalendarModel.m

#import "CalendarModel.h"

@implementation CalendarModel


+(JSONKeyMapper*)keyMapper
{
    return [[JSONKeyMapper alloc] initWithDictionary:@{
            @"gd$when": @"time",
            @"title.$t": @"title",
            }];
}

@end

Time.h

#import "JSONModel.h"

@protocol Time @end

@interface Time : JSONModel

@property (strong, nonatomic) NSString* startTime;
@property (strong, nonatomic) NSString* endTime;

@end

Time.m does nothing, as it's handled by JSONModel

SportsViewController.m

#import "SportsViewController.h"
#import "JSONModelLib.h"
#import "CalendarModel.h"
#import "Time.h"
#import "JSONValueTransformer.h"

@interface SportsViewController () 

@property (strong, nonatomic) NSMutableArray *events;
@property (strong, nonatomic) NSArray *music;

- (NSDate *)dateAtBeginningOfDayForDate:(NSDate *)inputDate;
- (NSDate *)dateByAddingYears:(NSInteger)numberOfYears toDate:(NSDate *)inputDate;

@end

@implementation SportsViewController

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    //make HTTP call
    NSString* searchCall = [NSString stringWithFormat:@"http://www.google.com/calendar/feeds/kao1d80fd2u5kh7268caop11o4%%40group.calendar.google.com/public/full?alt=json"];
    NSString* searchCall2 = [NSString stringWithFormat:@"http://www.google.com/calendar/feeds/3qag5m8iad46mtvsnnqbtrcjjg%%40group.calendar.google.com/public/full?alt=json"];

    [JSONHTTPClient getJSONFromURLWithString: searchCall
                                  completion:^(NSDictionary *json, JSONModelError *err) {

                                      //got JSON back
                                      NSLog(@"Got Sports JSON from web: %@", json);

                                      if (err) {
                                          [[[UIAlertView alloc] initWithTitle:@"Error"
                                                                      message:[err localizedDescription]
                                                                     delegate:nil
                                                            cancelButtonTitle:@"Close"
                                                            otherButtonTitles: nil] show];
                                          return;
                                      }

                                      //initialize the models
                                      _events = [CalendarModel arrayOfModelsFromDictionaries:
                                                json[@"feed"][@"entry"]
                                                ];

                                      if (_events) NSLog(@"Loaded successfully sports models");

                                      //show the Events
                                      [_events addObjectsFromArray:_music];
                                      NSLog(@"%@", _events);
                                      [self.tableView reloadData];

                                  }];

    [JSONHTTPClient getJSONFromURLWithString: searchCall2
                                  completion:^(NSDictionary *json2, JSONModelError *err2) {

                                      //got JSON back
                                      NSLog(@"Got Music JSON from web: %@", json2);

                                      if (err2) {
                                          [[[UIAlertView alloc] initWithTitle:@"Error"
                                                                      message:[err2 localizedDescription]
                                                                     delegate:nil
                                                            cancelButtonTitle:@"Close"
                                                            otherButtonTitles: nil] show];
                                          return;
                                      }

                                      //initialize the models
                                      _music = [CalendarModel arrayOfModelsFromDictionaries:
                                                json2[@"feed"][@"entry"]
                                                ];

                                      if (_music) NSLog(@"Loaded successfully music models");
                                      [_events addObjectsFromArray:_music];
                                      //show the Events
                                      [self.tableView reloadData];

                                  }];
    //[events addObjectsFromArray:music];
    [self.tableView reloadData];

}
;

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



- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - table methods
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return _events.count;
}

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    CalendarModel* event = _events[indexPath.row];


    NSString *dato = [[event.time objectAtIndex:0] startTime];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSSzzz";
    NSDate *gmtDate = [formatter dateFromString: dato];
    formatter.dateFormat = @"dd-MM-yyyy HH:mm";
    dato = [formatter stringFromDate:gmtDate];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SportCell" forIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"%@",
                           event.title
                           ];
    cell.detailTextLabel.text = dato;

    return cell;
}
@end

So basically all the data i need sorted resides in the _events array. I just do not get how i sort it by date into sections. The reason why startTime and endTime are NSStrings is that, that's what i am returned by the call to the shared calendar on Google

2
  • 1
    You mean group into sections and sort by time? Is each section = 1 day? Or you just want to list all the events sorted chronologically? Commented Mar 27, 2013 at 11:06
  • 1
    Each section would be a day, where an event is present. There are days with no events, days with 1 event or days with multiple events. I'd like the section header to be a date where 1 or more events was retrieved from the calendar. That way the section header would be the date (Time.startTime) (27/3-2013), the cell.textLabel.text would be the CalendarModel.Title, and the cell.detailTextLabel.text would be Time.startTime (converted to only use the actual time of day, the event starts) Commented Mar 27, 2013 at 11:16

1 Answer 1

13

First group all your events - you'll have to take care of variable scoping (I'm using days and groupedEvents locally but you'll have to declare those as ivars/properties)

    NSMutableArray *days = [NSMutableArray array];
    NSMutableDictionary *groupedEvents = [NSMutableDictionary dictionary];

- (void)groupEventsIntoDays
{
    for (CalendarModel *event in _events)
    {
        NSString *dato = [[event.time objectAtIndex:0] startTime];
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSSzzz";
        NSDate *gmtDate = [formatter dateFromString: dato];

        if (![days containsObject:gmtDate])
        {
            [days addObject:gmtDate];
            [groupedEvents setObject:[NSMutableArray arrayWithObject:event] forKey:gmtDate];
        }
        else
        {
            [((NSMutableArray*)[groupedEvents objectForKey:gmtDate]) addObject:event];
        }
    }

    days = [[days sortedArrayUsingSelector:@selector(compare:)] mutableCopy];
}

Section headers:

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0,0,tableView.frame.size.width, 30)];
    UILabel *headerLabel = [[UILabel alloc] initWithFrame:header.bounds];
    [header addSubview:headerLabel];

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"dd-MM-yyyy HH:mm";
    NSString *dateAsString = [formatter stringFromDate:[days objectAtIndex:section]];

    [headerLabel setText:dateAsString];

    return header;
}

I only touched the first two lines in your cellForRow - you can modify the rest as needed for display/formatting:

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    NSDate *date = [days objectAtIndex:indexPath.section];
    CalendarModel *event = [((NSMutableArray*)[groupedEvents objectForKey:date]) objectAtIndex:indexPath.row];

    NSString *dato = [[event.time objectAtIndex:0] startTime];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss.SSSzzz";
    NSDate *gmtDate = [formatter dateFromString: dato];
    formatter.dateFormat = @"dd-MM-yyyy HH:mm";
    dato = [formatter stringFromDate:gmtDate];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SportCell" forIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"%@",
                           event.title
                           ];
    cell.detailTextLabel.text = dato;

    return cell;
}
Sign up to request clarification or add additional context in comments.

12 Comments

You can also sort using NSSort Descriptors.!
Made the days and groupedEvents as properties. I'm getting to errors: On the line: _days = [_days sortedArrayUsingSelector:@selector(compare:)]; It says "Incompatible pointer types assigning NSMutableArray *_strong from NSArray" And on viewForHeaderInSection method it expects a return type i guess. It says Control reaches end of non-void function
My bad. Added mutableCopy to days which should take care of the warning, and added the return for the header view.
I get null values back. Added an NSLog to print _days, and nothing is in there. Is it the line "for (CalendarModel *event in _events)" that's troubling me? I wanted to use something like "for (Object *event in _events). Array output looks like this: ( "<CalendarModel> \n [title]: Everton v Stoke\n [time]: (\n \"<Time> \\n [startTime]: 2013-03-30T18:30:00.000+01:...\n</CalendarModel>",
You said you made days a property- did you init it, either with [[NSMutableArray alloc] init] or [NSMutableArray array]?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.