I have created a UITableView and set everything up so that it pulls the correct Data that I want on the table. The only issue I have is that when I click on an item, I want it to open that viewController
I have set the Storyboard ID up correctly so everything should work but please see my code below incase there's something obvious I've missed:
- (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];
*/
UIViewController *newTopViewController;
if (indexPath.section == 0) {
NSString *identifier = [NSString stringWithFormat:#"%#", [self.section1 objectAtIndex:indexPath.row]];
newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
} else if (indexPath.section == 1) {
NSString *identifier = [NSString stringWithFormat:#"%#", [self.section2 objectAtIndex:indexPath.row]];
newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
}
else if (indexPath.section == 2) {
NSString *identifier = [NSString stringWithFormat:#"%#", [self.section3 objectAtIndex:indexPath.row]];
newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
}
}
I can provide more info if needed
You use instantiateViewControllerWithIdentifier to create view controller objects.
But you are not presenting the created view controller object so add:
[self.navigationController presentViewController:newTopViewController animated:YES completion:nil];
If Identifiers are correct and you set segues in your storyboard then you can just call
[self performSegueWithIdentifier:indentifier sender:nil];
You need to either Push yournewTopViewController
[self.navigationController pushViewController:newTopViewController animated:YES];
Or Modally Present your newTopViewController
[self.navigationController presentViewController:newTopViewController animated:YES completion:nil];
in the end of your didSelectRowAtIndexPath Method.
To answer your question I believe you should first import all your .h files First.
Then you can go
if (indexPath.section == 0) {
FirstViewController *firstController = [[FirstViewController alloc] init];
[self presentViewController:firstController animated:YES completion:nil];
}
And so on and so forth
Related
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *storyViewController = [mainStoryBoard instantiateViewControllerWithIdentifier:#"StoryViewController"];
HistoryDetails *obj = [[HistoryDetails alloc]init];
obj.currentIndex = indexPath.row;
[self presentViewController:storyViewController animated:YES completion:nil];
}
Here is my TableViewController's didSelectRowAtIndexPath and with the selection of cell it will go to another viewController which is HistoryDetails.
Now I have a property currentIndex inHistoryDetails class and I set data to that property which is indexPath.row. But in HistoryDetails.m I am not getting the selected index value.(Always getting 0). where is fault in my code.
Probably you mean
HistoryDetails *storyViewController = (HistoryDetails *)[mainStoryBoard instantiateViewControllerWithIdentifier:#"StoryViewController"];
storyViewController.currentIndex = indexPath.row;
[self presentViewController:storyViewController animated:YES completion:nil];
instantiateViewControllerWithIdentifierreturns the requested view controller.
You need to cast the instantiated controller to the custom subclass.
I am new to IOS Objective C Programming. I am trying a very simple app. My main page is standard View Controller where i have a simple UITableView. What i am trying to do is to make a different view controller to come up when user select different cell on the Table View. Currently i populate 3 simple lines. I have searched for many historical discussion but can't seem to work (from segue options to simple instantiate view options). I give a snip of my code and hope that anyone can point me what i am doing wrong here.
Storyboard
Ensure one are you embed with NavigationController or Not, if Not,
just do the following way
XCode menu --> Editor --> EmbedIn --> Navigation Controller, do like
you get the output of
Step-2
In here we can navigate with two types
Connection Through
Connection less
Connection Through
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *SegName = #"";
if (indexPath.row == 0)
{
SegName = #"firstSegumeName";
}
else if (indexPath.row == 1)
{
SegName = #"secondSegumeName";
}
else if (indexPath.row == 2)
{
SegName = #"thirdSegumeName";
}
[self performSegueWithIdentifier:SegName sender:self];
}
Connection Less
if use `storyboard ID` with connection less
for example
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController *otherViewCon;
if (indexPath.row == 0)
{
otherViewCon = [self.storyboard instantiateViewControllerWithIdentifier:#"yourfirstIdentifierName"];
}
else if (indexPath.row == 1)
{
otherViewCon = [self.storyboard instantiateViewControllerWithIdentifier:#"yoursecondIdentifierName"];
}
else if (indexPath.row == 2)
{
otherViewCon = [self.storyboard instantiateViewControllerWithIdentifier:#"yourthirdIdentifierName"];
}
[self.navigationController pushViewController:otherViewCon animated:YES];
}
Create an array with segue names in the order in which you want to refer to the view controllers from your tableview and then in
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
you can call
[self performSegueWithIdentifier:[array valueAtIndex:indexPath.row sender:nil];
If its through XIB :
Your_ViewController *vc = [[Your_ViewController alloc] initWithNibName:#"Your_ViewController" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
If its through StoryBoard :
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main_storyboard" bundle:[NSBundle mainBundle]];
Your_ViewController *vc = [storyBoard instantiateViewControllerWithIdentifier:#"storyboardID"];
[[self navigationController] pushViewController:vc animated:YES];
If its through Coding :
Your_ViewController *vc = [[Your_ViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
For Your questions :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Put above code here according to your requirement....
}
Try this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
firstViewController *u = [[ContactDetailsVC alloc]init];
u= [self.storyboard instantiateViewControllerWithIdentifier:#"firstView"];
[self.navigationController pushViewController:u animated:YES];
}
Replace last 2 lines of didSelectRowAtIndexPath with:
UINavigationController *navC = [[UINavigationController alloc] initWithRootViewController:myView];
[self presentViewController:navC animated:YES completion:nil];
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog((#"This is didSelectRowAtIndexPAth"));
DetailViewController *detailViewController = [[DetailViewController alloc] init];
detailViewController.myDictionary = [self.placeArray objectAtIndex:[indexPath row]]
// This MyDictionary NSdictionary is declared in other viewController which is populated here ..
NSLog(#"My Dictionary: This is a MasterView one %#",detailViewController.myDictionary);
UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
detailViewController = [mystoryboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
//The below NSlog is showing the content , its not null still in next viewcontroller same variable showing null content
NSLog(#"My Dictionary: This is a MasterView two %#",detailViewController.myDictionary);
[self performSegueWithIdentifier:#"showDetail" sender:self];
}
Use PrepareForSegue for this purpose
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
DetailViewController * detailViewController = (DetailViewController*)segue.destinationViewController;
detailViewController.myDictionary = [self.placeArray objectAtIndex:index];
}
From did select just use the prepareForSegue method(Hope you have already used.) Set the presenting view controller option via xib or programmatically and just stop there.prepareForSegue will call automatically while presenting the view while using storyboard.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DetailViewController *detailViewController = [[DetailViewController alloc] init];
detailViewController.myDictionary = [self.placeArray objectAtIndex:[indexPath row]];
}
edit you did_select_method and try.
Is it possible to open different view controllers depending on witch table view cell user clicks? I tried to do that with:
[self presentViewController:obj animated:YES completion:nil];
but when next view is presented, there is no navigation bar and I can't go back to table view.
EDIT:
Here is MasterViewController class that I am using
#import "MasterViewController.h"
#interface MasterViewController () {
NSArray *viewArray;
}
#end
#implementation MasterViewController
#synthesize items,itemImges;
- (void)awakeFromNib
{
if ([[[UIDevice currentDevice] systemVersion] compare:#"7" options:NSNumericSearch] != NSOrderedAscending) {
self.preferredContentSize = CGSizeMake(320.0, 480.0);
}
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
}
self.title = NSLocalizedString(#"MasterTitle",#"Options:");
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
items = [NSArray arrayWithObjects:#"Media Explorer",#"Live TV",#"Settings",nil];
itemImges = [NSArray arrayWithObjects:
[UIImage imageNamed:#"listicon_guide.png"],
[UIImage imageNamed:#"listicon_livetv.png"],
[UIImage imageNamed:#"listicon_settings.png"],
nil];
// Do any additional setup after loading the view, typically from a nib.
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
MediaExpDetailViewController *DVCA = [self.storyboard instantiateViewControllerWithIdentifier:#"MediaExpDetailViewController"];
LiveTVDetailViewController *DVCB = [self.storyboard instantiateViewControllerWithIdentifier:#"LiveTVDetailViewController"];
SettingsDetailViewController *DVCC = [self.storyboard instantiateViewControllerWithIdentifier:#"SettingsDetailViewController"];
//Create Array of views
viewArray = [NSArray arrayWithObjects:DVCA, DVCB, DVCC, nil];
}
#pragma mark - Table View
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return items.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSString *object = items[indexPath.row];
UIImage *image = itemImges[indexPath.row];
cell.textLabel.text = [object description];
cell.imageView.image = image;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//for iPad
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
//something goes here
}
else { //for iPhone
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
MediaExpDetailViewController *objSynergy = (MediaExpDetailViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"MediaExpDetailViewController"];
[self.navigationController pushViewController:objSynergy animated:YES];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
}
#end
First set Storyboard IDs for your Next View controllers in Interface Builder and then.
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Check Row and Select Next View controller
if (indexPath.row == 1)
{
// Push Selected View
UIViewController *view1 = [self.storyboard instantiateViewControllerWithIdentifier:#"StoryboardID"];
[self.navigationController pushViewController:view1 animated:YES];
}
}
That's because
[self presentViewController:obj animated:YES completion:nil];
Presents the new view controller modally (over top of the existing visible controller). If you want to push to a new view controller using your navigation controller, you'll want to use this. Of course you'll want to make sure that the view controller you're pushing from is embedded within a UINavigationController.
[self.navigationController pushViewController:obj animated:YES];
And to answer your first question, yes it absolutely is possible. Just add some condition logic to your didSelectRowAtIndexPath: UITableViewDelegate method.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (someCondition) {
[self.navigationController pushViewController:obj animated:YES];
}else{
[self.navigationController pushViewController:otherObj animated:YES];
}
}
Modally presented view controllers don't have navigation bars by default. You have to embed them in a UINavigationController, in order to have one. You should also implement how to dismiss the presented view controller by yourself, calling dismissViewControllerAnimated at the appropriate times.
However, I'd recommend to push your view controllers (with pushViewControllerAnimated), instead of presenting them modally, if you don't specifically need the modal functionality.
I'm trying to create an iPad application with a similar user interface to Apple's Mail application, i.e:
RootView controller (table view) on the left hand side of the split view for navigation with a multiple view hierarchy. When a table cell is selected a new table view is pushed on the left hand side
The new view on the left side can update the detail view.
I can accomplish both tasks, but not together.
I mean I can make a multi-level table view in the RootController.
Or I can make a single-level table view in the RootController which can update the detailViewController.
Can anyone tell me how to make a multi-level table in the RootController which can update a detailViewController?
There is more source code at the link but below is the method in which I presume I have to declare a new detailViewController (which has to be put in the UISplitViewController):
- (void)tableView:(UITableView *)TableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *dictionary = [self.tableDataSource objectAtIndex:indexPath.row];
//Get the children of the present item.
NSArray *Children = [dictionary objectForKey:#"Children"];
//
if([Children count] == 0) {
/*
Create and configure a new detail view controller appropriate for the selection.
*/
NSUInteger row = indexPath.row;
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
if (row == 0) {
FirstDetailViewController *newDetailViewController = [[FirstDetailViewController alloc]initWithNibName:#"FirstDetailView" bundle:nil];
detailViewController = newDetailViewController;
}
if (row == 1) {
SecondDetailViewController *newDetailViewController = [[SecondDetailViewController alloc]initWithNibName:#"SecondDetailView" bundle:nil];
detailViewController = newDetailViewController;
}
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers//nothing happens.....
[viewControllers release];//
}
else {
//Prepare to tableview.
RootViewController *rvController = [[RootViewController alloc]initWithNibName:#"RootViewController" bundle:[NSBundle mainBundle]];
//Increment the Current View
rvController.current_level += 1;
//Set the title;
rvController.current_title = [dictionary objectForKey:#"Title"];
//Push the new table view on the stack
[self.navigationController pushViewController:rvController animated:YES];
rvController.tableDataSource = Children;
[rvController.tableView reloadData]; //without this instrucion,items won't be loaded inside the second level of the table
[rvController release];
}
}
Sorry, but I cannot post my source code as it contains sensitive information. When I have more time available I will create a separate project and upload the code somewhere.
Here are extracts of how I have done it so far (I welcome any feedback).
The RootViewController - Note I have 4 sections in my root table.
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Detail view logic
NSUInteger section = indexPath.section;
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
if (section == 2) {
ProductSearchDetailView *viewController = [[ProductSearchDetailView alloc] initWithNibName:#"ProductSearchDetailView" bundle:nil];
detailViewController = viewController;
//[viewController release];
}
else {
DetailViewController *defaultDetailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
detailViewController = defaultDetailViewController;
//[defaultDetailViewController release];
}
// Navigation logic
switch (section) {
case 0:
{
break;
}
case 1:
{
break;
}
case 2:
{
// new Navigation view
ProductSearchViewController *viewController = [[ProductSearchViewController alloc] initWithNibName:#"ProductSearchViewController" bundle:nil];
viewController.navigationItem.backBarButtonItem.title = #"Back";
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
break;
}
case 3:
{
StoreLocatorNavController *viewController = [[StoreLocatorNavController alloc] initWithNibName:#"StoreLocatorNavController" bundle:nil];
viewController.navigationItem.backBarButtonItem.title = #"Back";
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
break;
}
}
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];
// Dismiss the popover if it's present.
if (popoverController != nil) {
[popoverController dismissPopoverAnimated:YES];
}
// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).
if (rootPopoverButtonItem != nil) {
[detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}
[detailViewController release];
}
NSNotificationCenter part
Add this to ProductSearchViewController:
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *itemAtIndex = (NSDictionary *)[self.productResults objectAtIndex:indexPath.row];
[[NSNotificationCenter defaultCenter] postNotificationName:#"updateProduct" object:itemAtIndex];
}
And finally, add this to ProductSearchDetailViewController:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(updateTheProductDetails:) name:#"updateProduct" object:nil];
}
- (void)updateTheProductDetails:(NSNotification *)notification {
NSDictionary *productDictionary = [NSDictionary dictionaryWithDictionary:[notification object]];
// product name
_productName.text = [productDictionary objectForKey:#"ProductDescription"];
}
Hope it helps!