Reputation: 2051
Is there a better way to do the following in Xcode for iPhone app?
I have a main navigation UIViewController screen with 4 buttons on it.
Clicking button 1 shows a sub navigation UIViewController with 4 buttons on it. Clicking button 2 shows the same sub navigation UIViewController but with 5 buttons on it. Clicking button 3 shows the same sub navigation UIViewController but with 4 buttons on it. Clicking button 4 shows the same sub navigation UIViewController but with 6 buttons on it.
To handle this I have assigned tags to each button in the main navigation. When a button is clicked, I take this tag number and pass it to sub navigation UIViewController.
Then in the sub navigation UIViewController, based on this value, I manually draw/create the sub navigation buttons as needed.
Below is how I handle this in the sub navigation UIViewController. I check to see what value was passed from main navigation UIViewController, and draw the number of buttons accordingly. I also set custom background images for each button. And for each button click I have its own selector method. Note that some buttons in the sub navigation will go to a UIViewController while some buttons will go to a TableViewController. Also each sub navigation button will have to display its own "content" in its destination view.
Is there a better, more elegant way of handling this? It just seems like a lot of code duplication to me.The example below shortened for brevity.
// SubNavViewController.m
// SegueTest
#import "SubNavViewController.h"
#import "GettingHereViewController.h"
#import "TableViewController.h"
#import "GettingHereContent.h"
@interface SubNavViewController ()
@end
@implementation SubNavViewController
@synthesize tagNumber;
@synthesize buttonNumber;
@synthesize buttonPushedTrackNumber;
@synthesize hotelButton;
@synthesize bAndBButton;
@synthesize caravanButton;
@synthesize selfCateringButton;
@synthesize apartmentsButton;
.
.
.
etc (19 in total)
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.tagNumber == 1)
{
self.navigationItem.title = @"Getting Here";
// By Air Button
byAirButton = [UIButton buttonWithType:UIButtonTypeCustom];
byAirButton.tag = 1;
byAirButton.frame = CGRectMake(25, 140, 280.f, 40.f);
UIImage *airButton = [UIImage imageNamed:@"gettingHereByAirButton.png"];
[byAirButton setBackgroundImage:airButton forState:UIControlStateNormal];
[self.view addSubview:byAirButton];
[byAirButton addTarget:self action:@selector(byAirButtonClicked) forControlEvents:UIControlEventTouchUpInside];
// By Rail Button
byRailButton = [UIButton buttonWithType:UIButtonTypeCustom];
byRailButton.tag = 2;
byRailButton.frame = CGRectMake(25, 190, 280.f, 40.f);
UIImage *railButton = [UIImage imageNamed:@"gettingHereByRailButton.png"];
[byRailButton setBackgroundImage:railButton forState:UIControlStateNormal];
[self.view addSubview:byRailButton];
[byRailButton addTarget:self action:@selector(byRailButtonClicked) forControlEvents:UIControlEventTouchUpInside];
.
.
. etc (2 more button)
}
else if (self.tagNumber == 2)
{
self.navigationItem.title = @"Where to Stay";
// B&B Button
bAndBButton = [UIButton buttonWithType:UIButtonTypeCustom];
bAndBButton.tag = 1;
bAndBButton.frame = CGRectMake(25, 140, 280.f, 40.f);
UIImage *bedAndBreakfast = [UIImage imageNamed:@"whereToStayBedAndBreakfastButton.png"];
[bAndBButton setBackgroundImage:bedAndBreakfast forState:UIControlStateNormal];
[self.view addSubview:bAndBButton];
[bAndBButton addTarget:self action:@selector(bAndBButtonClicked) forControlEvents:UIControlEventTouchUpInside];
.
.
. etc (do this for the rest of the buttons)
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void) byAirButtonClicked
{
GettingHereContent *gettingHere = [GettingHereContent new];
gettingHere = @"By Air";
NSLog(@"Content: %@", gettingHere);
[self performSegueWithIdentifier:@"gettingHereSegue" sender:self];
}
- (void) bAndBButtonClicked
{
GettingHereContent *gettingHere = [GettingHereContent new];
gettingHere = @"Bed and Breakfast";
NSLog(@"Content: %@", gettingHere);
[self performSegueWithIdentifier:@"tableViewSegue" sender:self];
}
.
.
. (do this for all buttons - 19 in total)
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
}
@end
Upvotes: 1
Views: 3614
Reputation: 3303
First I would recommend to create a NS_ENUM defining all your buttons in the following way:
typedef NS_ENUM(NSUInteger, ButtonTag)
{
ButtonTagHotel,
ButtonTagOther,
...
}
Then in viewDidLoad: you could create an Array with all buttons, that are needed for your current state like the following way:
NSMutableArray *buttonTags = [[NSMutableArray alloc] init];
if (self.tagNumber == 1 || self.tagNumber == 3)
[buttonTags addObject: @(ButtonTagHotel)];
if (self.tagNumber == 5 || self.tagNumber == 8)
[buttonTags addObject: @(ButtonTagOther)];
// etc...
When you have build up your needed button tags, you can create and add them all in one loop:
uint cnt = 0;
for (NSNumber *tag in buttonTags)
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.tag = [tag unsignedIntValue];
btn.frame = CGRectMake(25, 20 + (cnt * 50.f), 280.f, 40.f);
UIImage *image = [UIImage imageNamed:@"genericButtonImage.png"];
[btn setBackgroundImage:image forState:UIControlStateNormal];
[self.view addSubview:btn];
[btn addTarget:self action:@selector(buttonTouched:) forControlEvents:UIControlEventTouchUpInside];
cnt++;
}
If you have to set a different image for every button, then you should create another array that is holding all image names indexed by the ButtonTag enum...
Now you just have to implement -(void)buttonTouched:(UIButton*)sender:
-(void)buttonTouched:(UIButton*)sender
{
switch (sender.tag) {
case ButtonTagHotel:
{
// do your stuff
}
break;
...
default:
break;
}
}
Upvotes: 1