Skip to content

Instantly share code, notes, and snippets.

@kharmabum
Created February 14, 2014 19:18
Show Gist options
  • Save kharmabum/9007199 to your computer and use it in GitHub Desktop.
Save kharmabum/9007199 to your computer and use it in GitHub Desktop.
For selecting mutually exclusive categories in a dependent hierarchy (i.e. tracing a taxonomy). See -> http://www.cocoanetics.com/2011/03/expandingcollapsing-tableview-sections/
#import <UIKit/UIKit.h>
@interface HPGroupSelectViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
@end
#import "HPGroupSelectViewController.h"
#import "DTCustomColoredAccessory.h"
#import "HPActionBar.h"
#import "HPApiClient.h"
#import "MBProgressHUD.h"
#import "HPUI.h"
#import "HPTitleLabel.h"
#import "HPUser.h"
@interface HPGroupSelectViewController ()
@property (strong, nonatomic) NSArray *sectionTitles;
@property (strong, nonatomic) NSMutableDictionary *selections;
@property (nonatomic, strong) NSMutableIndexSet *expandedSections;
@property (nonatomic, strong) UITableView *tableView;
@property (strong, nonatomic) HPTitleLabel *titleLabel;
@property (nonatomic, strong) NSDictionary *buildings;
@property (nonatomic, strong) NSArray *locations;
@property (nonatomic, strong) NSArray *departments;
@property (nonatomic, strong) NSDictionary *organizations;
@end
@implementation HPGroupSelectViewController
#pragma mark - UITableViewDataSource
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
return ([self currentSelectionFromSection:indexPath.section]) ? 60 : 44;
} else {
return 38;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 4;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return (![self.expandedSections containsIndex:section]) ? 1 : [self itemsForSection:section].count + 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
NSString *currentSelection = [self currentSelectionFromSection:indexPath.section];
if (indexPath.row == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:@"SectionCell"];
cell.accessoryView=nil;
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"SectionCell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.font = [HPUI fontWithName:@"Ronnia-SemiBold" size:20.0f];
cell.detailTextLabel.font = [HPUI fontWithName:@"Ronnia-Light" size:16.0f];
}
cell.textLabel.text = self.sectionTitles[indexPath.section];
cell.detailTextLabel.text = currentSelection;
DTCustomColoredAccessoryType accessoryType = ([self.expandedSections containsIndex:indexPath.section]) ? DTCustomColoredAccessoryTypeUp : DTCustomColoredAccessoryTypeDown;
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:accessoryType];
cell.accessoryView.userInteractionEnabled = NO;
cell.contentView.alpha = 1;
if (indexPath.section == 1 || indexPath.section == 3) {
if (![self currentSelectionFromSection:indexPath.section - 1]) cell.contentView.alpha = 0.4;
}
} else {
cell = [tableView dequeueReusableCellWithIdentifier:@"ItemCell"];
cell.accessoryView=nil;
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"ItemCell"];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.textLabel.font = [HPUI fontWithName:@"Ronnia-Regular" size:16.0f];
cell.textLabel.xOrigin += 20;
}
NSArray *sectionItems = [self itemsForSection:indexPath.section];
NSString *item = [sectionItems objectAtIndex:indexPath.row - 1];
cell.textLabel.text = [NSString stringWithFormat:@" %@", item];
cell.accessoryType = ([item isEqual:currentSelection]) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
}
return cell;
}
#pragma mark - UITableView Delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!indexPath.row) {
[self toggleSection:indexPath tableView:tableView];
} else {
NSArray *sectionItems = [self itemsForSection:indexPath.section];
NSString *currentSelection = self.selections[self.sectionTitles[indexPath.section]];
if (![currentSelection isEqual:[sectionItems objectAtIndex:indexPath.row - 1]]) {
self.selections[self.sectionTitles[indexPath.section]] = [sectionItems objectAtIndex:indexPath.row - 1];
} else {
[self.selections removeObjectForKey:self.sectionTitles[indexPath.section]];
}
if (indexPath.section == 0 || indexPath.section == 2)
[self.selections removeObjectForKey:self.sectionTitles[indexPath.section + 1]];
NSInteger countChild = (indexPath.section == 0 || indexPath.section == 2) ? 1 : 0;
[self.expandedSections removeIndex:indexPath.section];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(indexPath.section, 1 + countChild)] withRowAnimation:NO];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - Private
- (NSArray *)itemsForSection:(NSInteger)index
{
switch (index) {
case 0:
return self.departments;
case 1:
return [self.organizations objectForKey:[self currentSelectionFromSection:0]];
case 2:
return self.locations;
case 3:
return [self.buildings objectForKey:[self currentSelectionFromSection:2]];
default:
return nil;
}
}
- (NSString *)currentSelectionFromSection:(NSInteger)index
{
return self.selections[self.sectionTitles[index]];
}
-(void)toggleSection:(NSIndexPath*)indexPath tableView:(UITableView *)tableView
{
if ((indexPath.section == 1 || indexPath.section == 3) && ![self currentSelectionFromSection:indexPath.section - 1])
return;
BOOL currentlyExpanded = [self.expandedSections containsIndex:indexPath.section];
if (currentlyExpanded)
[self.expandedSections removeIndex:indexPath.section];
else
[self.expandedSections addIndex:indexPath.section];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
DTCustomColoredAccessoryType accessoryType = (!currentlyExpanded) ? DTCustomColoredAccessoryTypeUp : DTCustomColoredAccessoryTypeDown;
cell.accessoryView = [DTCustomColoredAccessory accessoryWithColor:[UIColor grayColor] type:accessoryType];
cell.accessoryView.userInteractionEnabled = NO;
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:NO];
}
-(void)didPressCancelButtonOnGroupEdit:(id)sender
{
[self.navigationController dismissModalViewControllerAnimated:YES];
}
- (void)failWithMessage:(NSString *)status
{
[MBProgressHUD hideHUDForView:self.view animated:YES];
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:NO];
[hud setLabelText:status];
[self performBlockOnMainThread:^{
[MBProgressHUD hideHUDForView:self.view animated:YES];
[self performBlockOnMainThread:^{hud.labelText = @"";} afterDelay:0.33f];
} afterDelay:1.5f];
}
-(void)finishSelectingGroup
{
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
NSMutableArray *savedGroups = [NSMutableArray arrayWithCapacity:4];
for (int i = 0; i < 4; i++) {
NSString *selection = [self currentSelectionFromSection:i];
if (selection) [savedGroups addObject:selection];
}
[HPApiClient saveGroupList:savedGroups success:^(NSDictionary *results) {
[MBProgressHUD hideAllHUDsForView: self.view animated:YES];
[self dismissModalViewControllerAnimated:YES];
[HPSessionManager activeUser].groups = [results objectForKey:@"groups"];
} failure:^(NSString *status, id json) {
[self failWithMessage:status];
}];
}
#pragma mark - VC Lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.expandedSections = [[NSMutableIndexSet alloc] init];
self.sectionTitles = @[@"Departments", @"Organizations", @"Locations", @"Buildings"];
self.selections = [[NSMutableDictionary alloc] initWithCapacity:4];
self.titleLabel = [[HPTitleLabel alloc] init];
self.navigationItem.titleView = self.titleLabel;
[self.titleLabel setTitleLabelText:@"Edit Groups"];
self.tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.yOrigin = 0;
self.tableView.height = self.view.height - self.navigationController.navigationBar.height - 44;
self.tableView.backgroundView = nil;
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageFromDiskNamed:@"gray_bg.png"]];
[self.view addSubview:self.tableView];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStyleDone target:self action:@selector(didPressCancelButtonOnGroupEdit:)];
HPActionBar *actionBar = [[HPActionBar alloc] initWithButtonType: HPTabbarActionButtonCheckMark];
[actionBar.actionButton setTarget:self action:@selector(finishSelectingGroup) forControlEvents:UIControlEventTouchUpInside];
actionBar.yOrigin = self.view.height - 44 - actionBar.height;
[self.view addSubview: actionBar];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[HPApiClient getGroupList:^(NSDictionary *results) {
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
NSDictionary *groups = results[@"groups"];
self.departments = groups[@"Departments"];
self.organizations = groups[@"Organizations"];
self.locations = groups[@"Locations"];
self.buildings = groups[@"Buildings"];
self.expandedSections = [[NSMutableIndexSet alloc] init];
[self.tableView reloadData];
} failure:^(NSString *status, id json) {
[self failWithMessage:status];
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment