Skip to content

Instantly share code, notes, and snippets.

@paulw11
Last active August 29, 2015 14:08
Show Gist options
  • Save paulw11/da11ab3c7688c6deb1d7 to your computer and use it in GitHub Desktop.
Save paulw11/da11ab3c7688c6deb1d7 to your computer and use it in GitHub Desktop.
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, DeliDay) {
DeliDaySunday=0,
DeliDayMonday=1,
DeliDayTuesday=2,
DeliDayWednesday=3,
DeliDayThursday=4,
DeliDayFriday=5,
DeliDaySaturday=6,
DeliDayUnknown=-1
};
@interface DeliData : NSObject
-(id)init:(NSData *)menuData;
-(NSArray *) itemsForMeal:(NSString *)meal onDay:(DeliDay)day atCounter:(NSString *)counter ;
-(NSArray *) mealsForDay:(DeliDay)day;
-(NSArray *) countersForMeal:(NSString *)meal onDay:(DeliDay)day;
+(DeliDay)deliDayForString:(NSString *)dayString;
+(NSString *)stringForDeliDay:(DeliDay)day;
@end
#import "DeliData.h"
#import "TFHpple.h"
#import "Item.h"
@interface DeliData ()
@property (strong,nonatomic) NSMutableArray *menuData;
@property (strong,nonatomic) NSMutableArray *dayMeals;
@end
@implementation DeliData
static NSArray *dayStrings=nil;
static dispatch_once_t onceToken;
-(id)init {
if (self=[super init]) {
[self populateMenuArray];
}
return self;
}
-(id)init:(NSData *)menuData {
if (self=[super init]) {
[self populateMenuArray];
[self parseXML:menuData];
}
return self;
}
-(void)populateMenuArray {
self.menuData=[NSMutableArray arrayWithCapacity:7];
self.dayMeals=[NSMutableArray arrayWithCapacity:7];
for (int i=0;i<7;i++) {
[self.menuData addObject:[NSMutableDictionary new]];
[self.dayMeals addObject:[NSMutableArray new]];
}
}
-(void)parseXML:(NSData *)menuData {
TFHpple *Parser = [TFHpple hppleWithXMLData:menuData];
NSString *XpathQueryString = @"//day";
NSArray *Nodes = [Parser searchWithXPathQuery:XpathQueryString];
for (TFHppleElement *element in Nodes) {
NSString *dayString=element.attributes[@"name"];
DeliDay day=[DeliData deliDayForString:dayString];
if (day != DeliDayUnknown) {
NSMutableDictionary *dayDict=(NSMutableDictionary *)self.menuData[day];
NSMutableArray *dayMeals=self.dayMeals[day];
NSArray *mealsArray=[element childrenWithTagName:@"meal"];
for (TFHppleElement *mealElement in mealsArray) {
NSString *mealName=mealElement.attributes[@"name"];
[dayMeals addObject:mealName];
NSMutableDictionary *counterDict=(NSMutableDictionary *)dayDict[mealName];
if (counterDict == nil) {
counterDict=[NSMutableDictionary new];
dayDict[mealName]=counterDict;
}
NSArray *countersArray=[mealElement childrenWithTagName:@"counter"];
for (TFHppleElement *counterElement in countersArray) {
NSString *counterName=counterElement.attributes[@"name"];
if (counterName!=nil) {
NSMutableArray *itemsArray=(NSMutableArray *)counterDict[counterName];
if (itemsArray == nil) {
itemsArray=[NSMutableArray new];
counterDict[counterName]=itemsArray;
}
NSArray *dishArray=[counterElement childrenWithTagName:@"dish"];
for (TFHppleElement *dishElement in dishArray) {
Item *newItem=[Item new];
TFHppleElement *dishNameElement=[dishElement firstChildWithTagName:@"name"];
NSString *text=[[dishNameElement firstTextChild].content stringByReplacingOccurrencesOfString:@"\n" withString:@""];
newItem.title=text;
TFHppleElement *dishUrlElement=[dishElement firstChildWithTagName:@"url"];
text=[[dishUrlElement firstTextChild].content stringByReplacingOccurrencesOfString:@"\n" withString:@""];
newItem.url=text;
[itemsArray addObject:newItem];
}
}
}
}
}
else {
NSLog(@"Invalid day name %@",dayString);
}
}
}
+(void)setupDayStrings {
dispatch_once(&onceToken, ^{
dayStrings = @[@"Sunday",@"Monday",@"Tuesday",@"Wednesday",@"Thursday",@"Friday",@"Saturday"];;
});
}
#pragma mark - Public methods
-(NSArray *) mealsForDay:(DeliDay)day {
return self.dayMeals[day];
}
-(NSArray *) countersForMeal:(NSString *)meal onDay:(DeliDay)day {
NSDictionary *mealsDict=(NSDictionary *)self.menuData[day];
NSDictionary *countersDict=(NSDictionary *)mealsDict[meal];
return [countersDict allKeys];
}
-(NSArray *) itemsForMeal:(NSString *)meal onDay:(DeliDay)day atCounter:(NSString *)counter
{
NSDictionary *mealsDict=(NSDictionary *)self.menuData[day];
NSDictionary *countersDict=(NSDictionary *)mealsDict[meal];
NSArray *itemsArray=countersDict[counter];
return itemsArray;
}
-(NSString *)description {
return self.menuData.description;
}
#pragma mark - Class methods
+(DeliDay)deliDayForString:(NSString *)dayString {
[DeliData setupDayStrings];
for (NSInteger i=0;i<dayStrings.count;i++) {
if ([dayString caseInsensitiveCompare:dayStrings[i]]==NSOrderedSame) {
return i;
}
}
return DeliDayUnknown;
}
+(NSString *)stringForDeliDay:(DeliDay)day {
[DeliData setupDayStrings];
return dayStrings[day];
}
@end
#import <Foundation/Foundation.h>
@interface Item : NSObject
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *url;
@end
#import "Item.h"
@implementation Item
-(id) init {
return [super init];
}
-(NSString *)description {
return [NSString stringWithFormat:@"%@ - %@",self.title,self.url];
}
@end
#import <UIKit/UIKit.h>
#import "DeliData.h"
@interface MenuTableViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
@property (strong,nonatomic) DeliData *deliData;
@property (assign) DeliDay day;
@property (strong,nonatomic) NSString *meal;
@end
#import "MenuTableViewController.h"
#import "Item.h"
@interface MenuTableViewController ()
@property (strong,nonatomic) NSArray *counters;
@property (weak,nonatomic) IBOutlet UISegmentedControl *segmentedControl;
@property (weak,nonatomic) IBOutlet UITableView *tableView;
@end
@implementation MenuTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSArray *meals=[self.deliData mealsForDay:self.day];
[self.segmentedControl removeAllSegments];
for (int i=0;i<meals.count;i++) {
[self.segmentedControl insertSegmentWithTitle:[meals[i] capitalizedString] atIndex:self.segmentedControl.numberOfSegments animated:NO];
}
self.meal=meals[0];
self.title=[NSString stringWithFormat:@"%@ - %@",[DeliData stringForDeliDay:self.day], self.meal];
self.segmentedControl.selectedSegmentIndex=0;
self.counters=[self sortCounters:[self.deliData countersForMeal:self.meal onDay:self.day]];
[self.tableView reloadData];
}
-(NSArray *)sortCounters:(NSArray *)inputArray {
NSMutableArray *outputArray=[inputArray mutableCopy];
NSArray *desiredOrder=@[@"Entrée",@"Pizza",@"Breakfast"];
NSInteger destination=0;
for (int i=0;i<desiredOrder.count;i++) {
NSInteger current=[outputArray indexOfObject:desiredOrder[i]];
if (current != NSNotFound) { // If found
if (current != destination) { // If not already in the right place
[outputArray exchangeObjectAtIndex:current withObjectAtIndex:destination++]; // Move into place
}
}
}
return outputArray;
}
-(IBAction)segmentedSelected:(id)sender
{
UISegmentedControl *segmentControl=(UISegmentedControl *)sender;
self.meal=[[segmentControl titleForSegmentAtIndex:segmentControl.selectedSegmentIndex] uppercaseString];
self.counters=[self sortCounters:[self.deliData countersForMeal:self.meal onDay:self.day]];
[self.tableView reloadData];
self.title=[NSString stringWithFormat:@"%@ - %@",[DeliData stringForDeliDay:self.day], self.meal];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
if (self.counters == nil) {
self.counters=[self.deliData countersForMeal:self.meal onDay:self.day];
}
return self.counters.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *items=[self.deliData itemsForMeal:self.meal onDay:self.day atCounter:self.counters[section]];
// Return the number of rows in the section.
return items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
NSArray *items=[self.deliData itemsForMeal:self.meal onDay:self.day atCounter:self.counters[indexPath.section]];
Item *rowItem=items[indexPath.row];
cell.textLabel.text=rowItem.title;
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return self.counters[section];
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
@end
#import "ViewController.h"
#import "DeliData.h"
#import "MenuTableViewController.h"
@interface ViewController ()
@property (strong,nonatomic) DeliData *delidata;
@property (weak,nonatomic) IBOutlet UITableView *tableView;
@property (strong,nonatomic) NSMutableArray *dayOrder;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *file = [[NSBundle mainBundle] pathForResource:@"menu" ofType:@"xml"];
NSString *str = [NSString stringWithContentsOfFile:file
encoding:NSUTF8StringEncoding error:NULL];
NSLog(@"str: %@", str);
self.delidata=[[DeliData alloc] init:[str dataUsingEncoding:NSUTF16StringEncoding]];
self.dayOrder=[NSMutableArray new];
NSCalendar *cal=[NSCalendar currentCalendar];
NSInteger dayNumber = [cal component:NSCalendarUnitWeekday fromDate:[NSDate date]]-1; // Sunday gives 0,
for (int i=0;i<7;i++) {
[self.dayOrder addObject:[NSNumber numberWithInteger:dayNumber]];
dayNumber=(dayNumber+1)%6;
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 7;
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSNumber *dayNumber=self.dayOrder[section];
return [self.delidata mealsForDay:[dayNumber integerValue]].count;
}
-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSNumber *dayNumber=self.dayOrder[section];
return [DeliData stringForDeliDay:[dayNumber integerValue]];
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
NSNumber *dayNumber=self.dayOrder[indexPath.section];
NSArray *meals=[self.delidata mealsForDay:[dayNumber integerValue]];
cell.textLabel.text=meals[indexPath.row];
return cell;
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"detailSegue"]) {
MenuTableViewController *destVC=(MenuTableViewController *)segue.destinationViewController;
destVC.deliData=self.delidata;
NSIndexPath *selectedPath=[self.tableView indexPathForSelectedRow];
destVC.day=selectedPath.section;
destVC.meal=[self.delidata mealsForDay:destVC.day][selectedPath.row];
[self.tableView deselectRowAtIndexPath:selectedPath animated:NO];
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment