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];
Related
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;
}
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.
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.
I have my first viewController "SFCrearMomentoViewController" and the second view is a tableViewController "MasterViewController". I need to select a row didSelectRowAtIndexPath and call the method didCelected which is implemented in my "first viewController" and close the view using dismissViewControllerAnimated.
The problem is that the method didCelected is never called. I've already tested this code in a test project using "two viewControllers" and it works but I don't know what's the problem in my current project.
SFCrearMomentoViewController.h
...
#import "MasterViewController.h"
#interface SFCrearMomentoViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextViewDelegate, MasterViewControllerDelegate>{
UIImagePickerController *picker;
}
...
SFCrearMomentoViewController.m
...
-(void)didSelected:(NSString *)nombre{
NSLog(#"didSelected method %#", nombre);
}
#end
MasterViewController.h
#import <UIKit/UIKit.h>
#protocol MasterViewControllerDelegate <NSObject>
#required
-(void) didSelected:(NSString *)nombre;
#end
#interface MasterViewController : UITableViewController
#property (weak, nonatomic) id <MasterViewControllerDelegate> delegate;
#end
MasterViewController.m
...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.delegate didSelected:#"row selected"];
[self dismissViewControllerAnimated:YES completion:nil];
}
...
Solution: I had to set the delegate self. I implemented it in the Segue.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.destinationViewController isKindOfClass:[MasterViewController class]]) {
MasterViewController *nextView = segue.destinationViewController;
nextView.delegate = self;
}
}
I had the same problem a few hours ago. In my case I set the delegate in prepareForSegue to the segue.destinationViewController but my destination view controller wasn't the View Controller with the delegate, it was a UINavigationController.
So I used this one:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"modalNeuerRaum"])
{
[(MyCustomModalViewController*)[(UINavigationController*)segue.destinationViewController viewControllers][0] setDelegate:self];
}
}
That worked for me, but I don't know if you have a UINavigationController..
You need to set the delegate in SFCrearMomentoViewController, you can do it in viewDidLoad, for example.
masterViewController.delegate = self;
I assume that you allocated and initialised new masterViewController object of MasterViewController type.
In my DetailViewController.h I've declared the property * type as seen below:
#interface DetailViewController : UIViewController
#property (strong, nonatomic) NSString *type;
#end
Then I got a ListViewController which is a UIViewController containing a TableView.
The ListViewController.h looks like this:
#interface ListViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#end
In my ListViewController.m I want to change the value of * type a soon I switch the View (view switching is working fine).
I'm doing this by adding the following:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UINavigationController * navigationController = [self.storyboard instantiateViewControllerWithIdentifier:#"DetailController"];
DetailViewController * detailController = [[DetailViewController alloc] init];
detailController.type = #"video";
NSLog(#"Type: %#", detailController.type);
[self.navigationController pushViewController:navigationController animated:YES];
}
When I put a breakpoint at the second line in this block/function I get detailController with in it * type.
When I NSLog this a few lines later it return "(null)".
The View is changed but but the type is not set.
I can't figure out what I'm doing wrong?
Someone who has a solution for this or can point me to something we're this is explained?
Because I tried searching for the answer but I couldn't find anything equivalent to my problem, or I used the wrong search terms..
in your didSelectRowAtIndexPath: method change the following lines`
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController * detailController = [self.storyboard instantiateViewControllerWithIdentifier:#"DetailController"];;
detailController.type = #"video";
NSLog(#"Type: %#", detailController.type);
[self.navigationController pushViewController: detailController animated:YES];
}`
in your storyboard select DetailViewController and give storyboard id as "DetailController". Make sure your ListViewController is embed in UINavigationController, you can do that by selecting ListViewController and go to editor->Embed in->Navigation Controller. Follow these steps and your problem will be solved.
OR you can give segue from your ListViewController to DetailViewController and use
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *path = [self.tableView indexPathForSelectedRow]; //create tableview outlet
[segue.destinationViewController setType:#"video"];
}
What is this for?
UINavigationController * navigationController = [self.storyboard instantiateViewControllerWithIdentifier:#"DetailController"];
Why are you pushing a navigation controller inside a navigation controller?
[self.navigationController pushViewController:navigationController animated:YES];
detailController was not used or displayed.
Try this instead:
[self.navigationController pushViewController:detailController animated:YES];
Look at the last line - you are telling the nav controller to push itself!
It should be like this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController * detailController = [self.storyboard instantiateViewControllerWithIdentifier:#"DetailController"];
detailController.type = #"video";
NSLog(#"Type: %#", detailController.type);
[self.navigationController pushViewController:detailController animated:YES];
}
Is the navigation controller and the alloc-init method both instantiates the save view controller??
If yes, try this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController * detailController = [[DetailViewController alloc] init];
detailController.type = #"video";
NSLog(#"Type: %#", detailController.type);
[self.navigationController pushViewController:detailController animated:YES];
}