Push new view controller from table view (subview) - ios

I have a view controller that has two table view controllers as subviews.
When I click one of the cells in the table view controller, I would like it to push to a new view controller. However, it says self.navigationController and self.parentViewController.navigationController are (null).
Does anyone know how I can push a new view from a subview? Thanks!
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
ProductClass *productClass = [arrProducts objectAtIndex:indexPath.row];
ProductSingleViewController *productSingleViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"ProductSingleViewController"];
productSingleViewController.prod_title = productClass.title;
NSLog(#"VC1: %#, VC2: %#", self.navigationController, self.parentViewController.navigationController);
[self.parentViewController.navigationController pushViewController:productSingleViewController animated:YES];
}

One way to handle this is by setting a delegate method inside the UITableViewControllers. Add the delegate method to your parent view controller. It will get triggered whenever someone taps a cell inside the tables. From this delegate method you will be able to push a new view controller onto the stack.
In MyTableViewController.h:
#protocol MyTableDelegate <NSObject>
#required
- (void)selectedCellWithInfo:(NSDictionary *)info
#end
#interface MyTableViewController : UITableViewController {
id <MyTableDelegate> delegate;
}
#property (strong) id delegate;
In MyTableViewController.m:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[delegate selectedCellWithInfo:[myTableDataSource[indexPath.row]];
}
In MyMainViewController.h:
#import "MyTableViewController.h"
#interface MyMainViewController : UIViewController <MyTableDelegate>
In MyMainViewController.m:
- (void)viewDidLoad {
[super viewDidLoad];
myTableViewController.delegate = self;
}
- (void)selectedCellWithInfo:(NSDictionary *)info {
// Do something
}

The navigationController property of a view controller will return a valid navigation controller object only if the view controller is in a navigation controller's navigation stack.
If the PRoductSingleViewController is your rootviewcontroller
1. Drag and drop the navigation controller
2. set the navigation controller as rootviewcontroller.
3. Replace the navigation child Viewcontroller with your PRoductSingleViewController
Or you can manage it in app delegate.m class
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
_productSingleViewController = [[PRoductSingleViewController alloc]initWithNibName:#"PRoductSingleViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController: _productSingleViewController];
[self.window addSubview:navController.view];
[navController release];
[self.window makeKeyAndVisible];
return YES;
}

Related

Starting a View Controller from a "nested" View Controller

I have a UIViewController which has another UIViewController added as a subview:
#import "ListViewController.h"
#interface SearchViewController ()
#end
#synthesize listController;
- (void)viewDidLoad {
[super viewDidLoad];
…
self.listController =[[ListViewController alloc] init];
[self.view insertSubview:listController.view belowSubview:mainTabBar];
self.listController.view.frame = CGRectMake(0, tabHeight, screenWidth, (screenHeight-tabHeight));
}
#end
The ListViewController has a TableView in it. On the click of an item in the TableView, I want to add a UIViewController to the Navigation Controller:
#import “PlaceViewController.h"
#interface ListViewController ()
#end
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
PlaceViewController *vc = [[PlaceViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
This works if the ListViewController is added to the Navigation Controller normally. But, in this case, when the ListViewController is basically "nested" within another, the newly added PlaceViewController is not opening. Is there a way to make this work? Thanks
You should create a parent/child relation between the container and the controller which has its view added. Some informations can be found in the intro of https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/ and more on the internet. Just look at custom container view controller.
Then you can get the navigationController property of your container from your ListViewController using the parentViewController property of ListViewController.

Calling UITABLEVIEW in other implementation IOS

I've a View Controller named as MasterViewController having a tableView implemented in it (as a part of my module). It contains following methods:
- (void)viewDidLoad
- (void)didReceiveMemoryWarning
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
Now I want to integrate my Module in My Main Project named as "myProject" having its view controller ViewController.
How Can I init my MasterViewController in ViewController i.e call its init method. My current approach is only loading (void)viewDidLoad method and showing empty table view in my ViewController keeping in view that my MasterViewController have an interface builder of storyboard named as Main
My Approach:
MasterViewController* mainVC = [[MasterViewController alloc] init];
[self.view insertSubview:mainVC.view belowSubview:tabBar];
What you can do is in viewDidLoad of ViewController class add the following;
In Viewcontroll.h:
- (void)viewDidLoad
{
.....
MasterViewController *MSVC = (MasterViewController * )[self.storyboard instantiateViewControllerWithIdentifier:#"Main"];
[self addChildViewController:MSVC];
[self.view addSubview:MSVC.view];
.....
}
Note that you have to call both addChildViewController and addSubview in order for your child view to display. You should not init your MasterViewController in your ViewController's init method.

how to push a uiviewcontroller from uitableview that is a subclass

I have a UIViewController in which I am adding a subclass of a UITableView as a subview.
e.g.
#interface ViewController : UIViewController
#interface ItemList : UITableView
in ViewController viewDidLoad I create a ItemList (itemList) object and add it to the view of the viewcontroller
- (void)viewDidLoad {
...
[self.view addSubview:itemList];
}
in the didSelectRowAtIndexPath of ItemList which is a UITableView I do not have access to the navigation controller so how do I push another viewcontroller on to the navigationcontroller?
#implementation ItemList
{
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.navigationController pushViewController:newViewControllerobject animated:YES];
}
}
Create a property eg : ViewController *mydelegate in itemList class.
when you add the itemList in ViewController's viewDidLoad add the following
itemList.myDelegate = self;
Moving ahead..on did select
#implementation ItemList
#synthesize mydelegate;
{
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[myDelegate.navigationController pushViewController:newViewControllerobject animated:YES];
}
}
If you have very first navigationController defined in AppDelegate, you can use the following code to find uppermost navigationController and then push the viewController upon it.
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
[appDelegate.navigationController.visibleViewController.navigationController pushViewController:newViewControllerobject animated:YES];

Switching between modal view controllers

My app allows the user to switch between two different modal view controllers (for two different styles of data entry). The code below used to work (in iOS 4.3 and earlier):
UIViewController * parent = current.parentViewController;
[current dismissModalViewControllerAnimated:NO];
svc.modalPresentationStyle = UIModalPresentationFormSheet;
[parent presentModalViewController:svc animated:NO];
[svc release];
but no longer (in iOS 5) - the "current" view controller dismisses, but "svc" is not presented.
Any idea why it broke (i.e. what did I do wrong)?
Any idea how to do it "right" (so that it works on 5.0 as well as 4.3 and earlier)?
Jeff Hay was totally right in his comment except for one thing. You should do it in the -viewDidAppear: method of the view controller which originally presented the first modal view controller.
Example:
// MyViewController.h
#interface MyViewController : UIViewController {
BOOL _shouldPresentSecondModalViewController;
}
#end
// MyViewController.m
#implementation MyViewController
- (void)viewDidAppear:(BOOL)animated {
if(_shouldPresentSecondModalViewController) {
UINavigationController *myNavCon;
// Code to create second modal navigation controller
[self presentModalViewController:myNavCon animated:YES];
_shouldPresentSecondModalViewController = NO;
}
}
- (void)presentFirstViewController {
UINavigationController *myNavCon;
// Code to create the first navigation controller
_shouldPresentSecondModalViewController = YES;
[self presentModalViewController:myNavCon animated:YES];
}
#end
EDIT:
Now, if you want to pass data between the two modal view controllers, you can use a delegate.
// FirstModalViewControllerDelegate.h
#protocol FirstModalViewControllerDelegate
#optional
- (void)controller:(FirstModalViewControllerDelegate *)vc shouldShowData:(id)anyType;
#end
// MyViewController.h
#interface MyViewController : UIViewController <FirstModalViewControllerDelegate> {
id _dataToDisplay;
}
#end
// MyViewController.m
#implementation MyViewController
- (void)viewDidAppear:(BOOL)animated {
if(_dataToDisplay != nil) {
UINavigationController *myNavCon;
// Code to create second modal navigation controller
[self presentModalViewController:myNavCon animated:YES];
[_dataToDisplay release];
_dataToDisplay = nil;
}
}
- (void)presentFirstViewController {
UINavigationController *myNavCon;
FirstModalViewController *myCon;
// Code to create the first modal view controller
[myCon setDelegate:self];
myNavCon = [[UINavigationController alloc] initWithRootViewController:myCon];
[self presentModalViewController:myNavCon animated:YES];
[myNavCon release];
}
- (void)controller:(FirstModalViewControllerDelegate *)vc shouldShowData:(id)anyType {
/* This method will get called if the first modal view controller wants to display
some data. If the first modal view controller doesn't call this method, the
_dataToDisplay instance variable will stay nil. However, in that case, you'll of
course need to implement other methods to, like a response to a Done button, dismiss
the modal view controller */
[self dismissModalViewController];
_dataToDisplay = [anyType retain];
}
#end

Receive a ViewDidUnload message through UINavigationControllerDelegate

DetailViewController <-> MasterViewController <-> ViewController
At the moment I solve my problem by having a variable in the ViewController class point to the DetailViewController so that I can perform a method when the DONE button in ViewController is pressed.
- (void)doneButtonPressed {
[self.detailViewController method];
}
What I want to do is to have the ViewController report to DetailViewController when it unloads, so that DetailViewController can perform the method itself.
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[self.navigationController delegate] performSelector:#selector(method)];
}
What I have tried is to have the MasterViewController set the ViewControllers delegate to DetailViewController with this code, when it is pushed:
ViewController *ViewController = [[ViewController alloc] init];
ViewController.navigationController.delegate = self.detailViewController;
[self.navigationController pushViewController:ViewController animated:YES];
UINavigationControllerDelegate has been set in DetailViewController.
What am I doing wrong?
My question was badly formulated.
The answer is in the documentation:
View Controller Programming Guide for iOS
-> Modal View Controllers
Dismissing a Modal View Controller
http://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html#//apple_ref/doc/uid/TP40007457-CH111-SW14

Resources