UITableView segue not working - ios

I followed the SimpleDrillDown app example in the docs for a workout app that shows workout names in the first UITableView and exercises in the second UITableView.
My app is in Dropbox here: http://db.tt/V0EhVcAG
I used storyboards, have prototype cells, but when I load in simulator the first UITableView won't let me click and go to the detail UITableView. The disclosure indicator chevrons don't load. The app builds successfully and there are no formal errors.
My tableviews are in a navigation controller, my segue and prototype cells are all named accordingly in storyboard.
SpitfireViewController.m
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [dataController countOfList];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"WorkoutCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Workout *workoutAtIndex = [dataController objectInListAtIndex:indexPath.row];
cell.textLabel.text = workoutAtIndex.title;
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showExercises"]) {
NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
DetailViewController *detailViewController = [segue destinationViewController];
detailViewController.workout = [dataController objectInListAtIndex:selectedRowIndex.row];
}
}
DetailViewController.m
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [workout.exercises count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ExerciseCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [workout.exercises objectAtIndex:indexPath.row];
return cell;
}
AppDelegate.h
#import <UIKit/UIKit.h>
#class DataController;
#class SpitfireViewController;
#interface SpitfireAppDelegate : UIResponder <UIApplicationDelegate>
{
UIWindow *window;
SpitfireViewController *spitfireViewController;
DataController *dataController;
}
#property (strong, nonatomic) UIWindow *window;
#end
AppDelegate.m
#import "SpitfireAppDelegate.h"
#import "SpitfireViewController.h"
#import "DataController.h"
#implementation SpitfireAppDelegate
#synthesize window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
spitfireViewController = [[SpitfireViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:spitfireViewController];
DataController *controller = [[DataController alloc] init];
spitfireViewController.dataController = controller;
[window addSubview:[navController view]];
[self.window makeKeyAndVisible];
return YES;
}
#end

If you have tableview cell segue selection issue.
You need to check first that your tableview allows selection
You do not need to implement UITableViewDelegate and UITableViewDataSource when using "Static cells"
You need to add a segue for the accessory action + a segue for the selection.

When using Storyboards, you'll typically set the storyboard file name in the Project settings under the info tab. Once you've selected your storyboard there, you can basically delete everything except the return YES part of the application:didFinishLaunchingWithOptions: method. It's all taken care of for you in the storyboard.
EDIT:
Here's where you set the storyboard:
Also make sure that your view controller is set as the initial view controller:

I think this is your problem:
spitfireViewController = [[SpitfireViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:spitfireViewController];
DataController *controller = [[DataController alloc] init];
spitfireViewController.dataController = controller;
The spitfireViewController you create here is not the one in your storyboard, it's a new one. You should delete all this code, as you already have a spitfireViewController embedded in a navigation controller that you made in the storyboard. You should set the data controller for spitfireViewController in it's viewDidLoad method:
DataController *controller = [[DataController alloc] init];
self.dataController = controller;

Where is your "didSelectRowAtIndexPath" method?
I would recommend putting that in and then triggering [self performSegueWithIdentifier:] to trigger the segue using the data in the table cell as the sender.

Related

How to pass NSObject class particular data from one class to another class in ios

In my ios app I have created one NSModel Object for displaying tableList and when I tapped on tableList row I want to take that particular model class object data to another class
How can I do this?
my code:
NSMutableArray * mainArray;
//TableList Delegate Methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return mainArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"HistoryCell";
// Similar to UITableViewCell, but
UITableViewCell *cell = (UITableViewCell *)[MaintableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
model1 = mainArray[indexPath.row];
cell.textLabel.text = model1.Name;
cell.detailTextLabel.text = model1.MasterId;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
ViewController1 *Controller = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController1"];
Controller.indexPosition = indexPath.row;
[self.navigationController pushViewController:Controller animated:YES];
}
#end
ModelObject1:
#import "ModelObject1.h"
#implementation ModelObject1
#synthesize MasterId,Name;
-(void)loadingservices :(id)mainDictionary{
NSLog(#"loadingservices %#",mainDictionary);
Name = [mainDictionary objectForKey:#"Name"];
MasterId = [mainDictionary objectForKey:#"MasterId"];
}
#end
Create one model object in your Destination View controller
#property (strong,nonatomic) ModelClass *job;
in your did select method get that model data and pass it
ModelClass *SelectedJob;
SelectedJob = [muarrJobs objectAtIndex:indexPath.row];
JobDescriptionViewController *obj = [self.storyboard instantiateViewControllerWithIdentifier:#"JobDescription"];
obj.job = SelectedJob;
[self.navigationController pushViewController:obj animated:YES];
Use this Code,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
ViewController1 *Controller = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController1"];
model1 = mainArray[indexPath.row];
Controller.modelVal = model1;
[self.navigationController pushViewController:Controller animated:YES];
}
Another ViewControllerB:
ViewControllerB.h
declare the property Value
#property (strong, nonatomic)modelName *modelVal;
ViewControllerB.m
print the name value in viewDidLoad:
NSLog(#"%#",modelVal.Name);
hope its helpful
Try like below:
1) Create one model object in your ViewController1
#property (strong,nonatomic) ModelObject1 *modelObj;
2) Write below code in viewDidLoad of ViewController1,
modelObj = [[ModelObject1 alloc]init];
Then Replace your didSelect method like this,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
ViewController1 *Controller = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController1"];
Controller.indexPosition = indexPath.row;
ModelObject1 *model = mainArray[indexPath.row];
Controller.modelObj = model;
[self.navigationController pushViewController:Controller animated:YES];
}
Then get you data from model class in viewDidLoad of ViewController1
e.g, NSLog("%#", modelObj.Name);
This way you can pass model class object to other view controller. Hope this will help you.

select a viewcontroller programatically at didiSelectRowAtIndexpath in ios

I have a tableview with dynamic prototypes content. I want to call for a specific ViewController programatically when a dynamic cell tap. I used SWRevealViewController calls for my project.
When I tap on cell one with #"l1" identifier I want to load main view controller with sw_front , used in SWRevealViewController. I cannot use controll+drag becaue in her I have use tabviewcontrller. When I do that it disappear the tab bar.
#import "ListViewController.h"
#interface ListViewController ()
#end
#implementation ListViewController
{
NSArray *menuItems;
}
- (void)viewDidLoad {
[super viewDidLoad];
menuItems = [NSArray arrayWithObjects:#"l1",#"l2",#"l3",#"l6",#"l4",#"l5",#"l7", nil];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [menuItems count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [menuItems objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell.reuseIdentifier isEqualToString:#""]) {
UIViewController *mainviewcontroller = [[UIViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:mainviewcontroller];
[self.navigationController presentViewController:navi animated:YES completion:nil];
}
}
If you already set storyboard ID then you can push programmatically using following code.
Here viewController1, viewController2 etc are storyboard Id of individual UIViewController.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *pushViewController = [self.storyboard instantiateViewControllerWithIdentifier:[NSString stringWithFormat:#"viewController%ld",indexPath.row]];
[self.navigationController pushViewController:pushViewController animated:YES];
}

iOS - How to prevent all my titles from changing

Right now I have a kind of pop-up selector so that the user can pick an option on my screen. Please see this sample project to see what I mean.
I'm using the same method as this sample, except that I have three different buttons where the user will select. My problem is that I am using this code:
- (void)itemSelectedatRow:(NSInteger)row
{
NSLog(#"row %lu selected", (unsigned long)row);
[self.selectSeverity setTitle:[self.severityArray objectAtIndex:row] forState:UIControlStateNormal];
[self.selectStatus setTitle:[self.statusArray objectAtIndex:row] forState:UIControlStateNormal];
[self.selectGender setTitle:[self.genderArray objectAtIndex:row] forState:UIControlStateNormal];
}
...and it is changing the name of the button for all three every time the user selects one. So for example, if the user taps the "selectSeverity" button, and chooses the item on row three, the name for the selectStatus and selectGender button will also change to the item on row three on its own corresponding array.
What I need to do is somehow separate this method so the button's title changes only when a row has been selected in its own array: how can I do this?
More information:
I have these tableViews embedded in a Navigation Controller:
statusViewController.m/.h
genderViewController.m/.h
pickerViewController.m/.h (this corresponds to the Severity button)
Each have a delegate with a separate ID, but the same content:
#protocol correspondingViewControllerDelegateHere <NSObject>
#required
- (void)itemSelectedatRow:(NSInteger)row;
#end
#interface correspondingViewControllerHere : UITableViewController
#property (strong, nonatomic) NSArray *correspondingArrayHere;
#property (assign, nonatomic) id<statusViewControllerDelegate> delegateIdHere;
#end
Each have the same content in the .m file as well, but correspond to their own delegates, arrays, etc.
#implementation statusViewController
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.statusData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"CellIdentifierHere";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [self.statusData objectAtIndex:indexPath.row];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([self.delegateIdHere respondsToSelector:#selector(itemSelectedatRow:)]) {
[self.delegateIdHere itemSelectedatRow:indexPath.row];
[self dismissViewControllerAnimated:YES completion:nil];
}
}
#end
In manualViewController.h (this is the view where they are implemented) I have declared the delegates.
Lastly, in the file manualViewController.m, I have the following code to implement them:
- (IBAction)showinfo:(id)sender
{
UINavigationController *navigationController = (UINavigationController *)[self.storyboard instantiateViewControllerWithIdentifier:#"pickerVC"];
pickerViewController *tableViewController = (pickerViewController *)[[navigationController viewControllers] objectAtIndex:0];
tableViewController.severityData = self.severityArray;
tableViewController.navigationItem.title = #"Triage Severity Levels";
tableViewController.delegate1 = self;
[self presentViewController:navigationController animated:YES completion:nil];
}
- (IBAction)showStatus:(id)sender {
UINavigationController *navigationController = (UINavigationController *)[self.storyboard instantiateViewControllerWithIdentifier:#"statusVC"];
statusViewController *tableViewController = (statusViewController *)[[navigationController viewControllers] objectAtIndex:0];
tableViewController.statusData = self.statusArray;
tableViewController.navigationItem.title = #"Triage Severity Levels";
tableViewController.delegate3 = self;
[self presentViewController:navigationController animated:YES completion:nil];
}
- (IBAction)showGender:(id)sender {
UINavigationController *navigationController = (UINavigationController *)[self.storyboard instantiateViewControllerWithIdentifier:#"genderVC"];
genderViewController *tableViewController = (genderViewController * [[navigationController viewControllers] objectAtIndex:0];
tableViewController.genderData = self.genderArray;
tableViewController.navigationItem.title = #"Triage Severity Levels";
tableViewController.delegate2 = self;
[self presentViewController:navigationController animated:YES completion:nil];
}
SO as I said before, I think the code lies in the itemSelectedAtRow. Can someone help me separate this method so that the choice of one item does not affect the choice of another item?
Thanks
One solution is to change the protocol to require three different methods
#protocol correspondingViewControllerDelegateHere <NSObject>
#required
- (void)itemSelectedSeverityAtRow:(NSInteger)row;
- (void)itemSelectedStatusAtRow:(NSInteger)row;
- (void)itemSelectedGenderAtRow:(NSInteger)row;
#end
Then implement the three methods in the manualViewController and call the appropriate method from each of the other view controllers.

Switching UIViewControllers in iOS not working

I am trying to show a UIViewController on top of other UIViewcontroller using addChildViewController functionality.The childViewController is a tableView which shows up on top of my MainViewController however I do not see the table view that it has.If I execute the childViewController separately , the tableView works fine , so what am I missing here.
Here's how I am adding a childVC:
#implementation Test2ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (IBAction)showChildVC:(id)sender
{
TestTableViewController *tVC = [[TestTableViewController alloc]init];
tVC.view.frame = CGRectMake(50, 50, 200, 200);
[self addChildViewController:tVC];
[self.view addSubview:tVC.view];
[tVC didMoveToParentViewController:self];
}
And this is the childVC that I want to show: .h
#import <UIKit/UIKit.h>
#interface TestTableViewController : UIViewController<UITableViewDataSource>
{
NSArray *array;
}
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
And: .m
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
array = [NSArray arrayWithObjects:#"One",#"Two",#"Three",#"Four", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [array objectAtIndex:indexPath.row];
return cell;
}
I see your table view in the second view controller is an IBOutlet, so you are placing it in Storyboard.
Then when you instantiate it, you can't do: [[TestTableViewController alloc]init]; you have to do:
[storyBoard instantiateViewControllerWithIdentifier:#"tVCStoryBoardID"];

Adding an Array to a UITableView, using a UINavigationController on a Tab Bar based application

I have made simple cocoa touch apps before but I have never used UINavigationControllers, any advice would be greatly appreciated.
I'm trying to add an array of a list of store names to a UITableView. The UITableView is accessed through a UINavigation controller by a tab on a tab bar.
I have a TabBarController.xib file that holds the tab bar.
I also have a AtoZNavigationController.xib that holds the UINavigationController.
And I have a AtoZTableController.xib file that holds the UITableView.
This is my AppDelegate.h:
#import <UIKit/UIKit.h>
#class AtoZNavigationController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) IBOutlet UITabBarController *rootController;
#property (strong, nonatomic) IBOutlet AtoZNavigationController *navController;
#end
The AppDelegate.m
#import "AppDelegate.h"
#import "AtoZNavigationController.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize rootController;
#synthesize navController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
[[NSBundle mainBundle] loadNibNamed:#"TabBarController" owner:self options:nil];
[self.window addSubview:rootController.view];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
#end
The AtoZNavigationController.h
#import <UIKit/UIKit.h>
#interface AtoZNavigationController : UINavigationController
#end
The AtoZNavigationController.m
#import "AtoZNavigationController.h"
#interface AtoZNavigationController ()
#end
#implementation AtoZNavigationController
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
-(void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
The AtoZTableController.h
#import <UIKit/UIKit.h>
#interface AtoZTableController : UITableViewController <UITableViewDelegate, UITableViewDataSource>
{
IBOutlet UITableView *AtoZTableView;
NSMutableArray *AtoZArray;
}
#property (nonatomic, retain) IBOutlet UITableView *AtoZTableView;
#end
The AtoZTableController.h
#import "AtoZTableController.h"
#interface AtoZTableController ()
#end
#implementation AtoZTableController
#synthesize AtoZTableView;
-(id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(#"A to Z", #"An A to Z List of Stores");
AtoZArray = [[NSMutableArray alloc] init];
[AtoZArray addObject:#"Apple"];
[AtoZArray addObject:#"Boots"];
[AtoZArray addObject:#"Topman"];
}
-(void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 0;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [AtoZArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
NSInteger row = [indexPath row];
cell.textLabel.text = [AtoZArray objectAtIndex:row];
return cell;
}
#pragma mark - Table view delegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
In your AtoZTableController.h, you have a problem.
The problem is in your 'tableView:cellForRowAtIndexPath:' method.
Here's what you have:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
NSInteger row = [indexPath row];
cell.textLabel.text = [AtoZArray objectAtIndex:row];
return cell;
}
The problem is that you never handle for a return value of nil from dequeueReusableCellWithIdentifier:CellIdentifier.
Try this out:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// What happens if you don't get a cell to use?
// This is the way to create a new, default UITableViewCell
if (!cell) {
// You can look at the UITableViewCell class reference to see the 4 available styles
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSInteger row = [indexPath row];
cell.textLabel.text = [AtoZArray objectAtIndex:row];
return cell;
}
Edit/Update:
OK, so it's a little bit difficult to know exactly where your error is, so I'll set up/describe for you a typical situation (or how I'd do it in your shoes).
If you create a new app and select the "Tabbed Application" template in Xcode, you get the following method in your app delegate (more or less; I condensed it a little bit and "fixed" Apple's poor choice to use dot notation):
Note: I believe the problem you're having with pushing a new view controller will be fixed below now...End Note
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]];
// Override point for customization after application launch.
UIViewController *vc1 = [[FirstViewController alloc] initWithNibName:#"FirstVC" bundle:nil];
// New line...
UINavigationController *navC = [[UINavigationController alloc] initWithRootViewController:vc1];
UIViewController *vc2 = [[SecondViewController alloc] initWithNibName:#"SecondVC" bundle:nil];
[[self setTabBarController:[[UITabBarController alloc] init]];
// Change here, too...
[[self tabBarController] setViewControllers:[NSArray arrayWithObjects:navC, vc2, nil]];
[[self window] setRootViewController:[self tabBarController]];
[[self window] makeKeyAndVisible];
return YES;
}
This method sets up all you need to launch your app with 2 UIViewControllers created and set as tab 1 and tab 2 inside of a UITabBarController.
Now, you can make FirstViewController and SecondViewController be whatever you want. For purposes of this question, we'll assume that you want to alter FirstViewController to host a UITableView, which will push a detail UIViewController when a user selects a row on the screen.
Requirements
EITHER FirstViewController must be a subclass of UITableViewController (this is not what the default template provides) OR you must add a UITableView onto FirstViewController's view and set up all of the connections.
Let's assume you're going to keep FirstViewController as a standard UIViewController subclass and that you'll add a UITableView onto its view. (I'd probably change it to a UITableViewController subclass, but that might be more confusing at this point.)
First, in FirstViewController.h, change this:
#interface MMFirstViewController : UIViewController
#end
to this:
#interface MMFirstViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
UITableView *TableView;
}
#property (strong, nonatomic) IBOutlet UITableView *TableView;
#end
Next, in FirstViewController.m, synthesize the TableView property (#synthesize TableView).
Next, click on FirstViewController.xib in Xcode to have it load up in Interface Builder (I'm assuming here that you're using Xcode 4).
Now, drag a UITableView from the controls panel onto your UIViewController's view.
Make the following connections in Interface Builder:
Right click on File's Owner and connect the TableView property to the UITableView you dropped on the view of FirstViewController.
Right click on the UITableView and connect BOTH the datasource AND delegate properties to File's Owner.
Now, the code you posted initializing and populating AtoZArray should work fine. Don't forget to copy in the 3 UITableView methods you previously had, numberOfSectionsInTableView:, tableView:numberOfRowsInSection: and tableView:cellForRowAtIndexPath:.
Those steps should get you working and should also let you see where you perhaps went wrong in your setup. Please note, you'll still have to figure out tableView:didSelectRowAtIndexPath: on your own in order to push in your new UIViewController.
Here's a teaser to get you started:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
ThirdViewController *detailVC = [[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil];
[[self navigationController] pushViewController:detailVC animated:YES];
}
I had to create an instance of the navigationController and pass that into the subview in my appDelegate.m along with the tabBarController. It can then later be referenced in my UITableViewController.
Here's the code I added:
navigationController = [[UINavigationController alloc] initWithRootViewController:_tabBarController];
[self.window addSubview:_tabBarController.view];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
Where navigationController is simply an instance of a subclass of either UITableViewController or UIViewController, depending on what type of screen you want to display.

Resources