I have UIViewController that contain another two UIViewControllers as properties.
MenuViewController contains:
#property (nonatomic, strong) TeamsViewController *teamsViewController;
#property (nonatomic, strong) ResultsViewController *resultsViewController;
The MenuViewController contains table view and when user tap on the cell "show teams" I need to initialize teamsViewController and show teamsViewController view. The same thing when user press on the cell "show results" but in this case I need to show resultsViewController view.
So, I usually do this is in one way initialize controllers when cell is pressed and call addSubview method that will add controllers view. But I think it is not good solution am I right?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (_teamsViewController) _teamsViewController = nil;
_teamsViewController = [TeamsViewController new]
[self.view addSubView:_teamsViewController];
}
Is the method above ok?
There is my hierarchy of view each of them managed by its own controller. So the white you managed by MenuViewController and the gray view managed by ResultViewController and blue view managed by TeamsViewController.
As I said before when I tap on appropriate cell in menu view controller I need to show teams or results. But each of this view has another view controller. Or maybe I confused about view controller paradigm? Maybe TeamsViewController should be a TeamsView and ResultsViewController should be ResultsView ? So both view controllers has the table as well that managed in their controllers. So i don't think it has to be a UIView instead of UIViewController.
I think your best bet is to set this up as a UINavigationController. UINavigationController inherits from UIViewController so you aren't losing any functionality this way. You could then set it up like this:
//MenuViewController.h
#interface MenuViewController : UINavigationController
#property (nonatomic, strong) TeamsViewController *teamsViewController;
#property (nonatomic, strong) ResultsViewController *resultsViewController;
//Insert other properties and methods....
#end
and in the method called when someone clicks on a cell, you would simply do this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.teamsViewController) {
self.teamsViewController = [[UIViewController alloc] initWithNibName:#"nibName" bundle:nil];
}
[self pushViewController:self.teamsViewController animated:YES];
}
Now, you have two view controllers, so you have to tell your method above which one to push onto the stack. If the rows are fixed, you can simply decide which one to show based on indexPath but if it's more dynamic (i.e. tableview is created from a database) then you'll need to have some more complex logic code here.
Without making too many assumptions, but to give you some general guidance, when you create a cell you would generally set some sort of flag on it to indicate what type it is. This can be done with an NS_ENUM or with a simple BOOL if you only have two states (I prefer to use ENUMs whenever possible as they are much more descriptive). You would then check for the existence of that flag in the tableView:didSelectRowAtIndexPath: method, pushing the corresponding view onto the navigation stack. Something like this (this is not literal code, but shown just to give you an idea:
// This code assumes in the method tableView:cellForRowAtIndexPath:
// you have set the tag property to '1' if a TeamsViewController is
// needed or '2' if a ResultsViewController is needed when that cell
// is pressed.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.teamsViewController = self.teamsViewController ? self.teamsViewController : [[UIViewController alloc] initWithNibName:#"TeamsViewController" bundle:nil];
self.resultsViewController = self.resultsViewController ? self.resultsViewController : [[UIViewController alloc] initWithNibName:#"ResultsViewController" bundle:nil];
switch ([[tableView cellForRowAtIndexPath:indexPath] tag]) {
case 1:
[self pushViewController:self.teamsViewController animated:YES];
break;
case 2:
[self pushViewController:self.resultsViewController animated:YES];
break;
default:
break;
}
}
You would still need to do your initialization in your teams or results view controller to show the view but this should steer you in the general direction.
I'd recommend using Storyboards and making sure to have a "Storyboard ID" for each of them. That way, it becomes a bit easier to push various UIViewController instances, as needed. This is my typical pattern:
UIViewController *vc = [self.storyboard
instantiateViewControllerWithIdentifier:#"selected identifier"];
[self.navigationController pushViewController:vc animated:YES];
Also, unless you need to set properties in the child view controller, there's no need to have a property reference to it. Further, this answer assumes that you're using a UINavigationController, with your MenuViewController set as the rootViewController. You can either set this up in IB with a Storyboard (easy and probably the preferred way), or in code like this:
MenuViewController *vc = [[UIViewController alloc] initWithNibName:#""
bundle:nil];
UINavigationController *navVc = [[UINavigationController alloc]
initWithRootViewController:vc];
Related
I have a ViewController (with a container view) embedded in a Navigation controller. The container contains a pageViewController with one of the 'pages' being a TableViewController (with UITableView outlet: 'aTableView'). I want to trigger the edit mode in the tableViewController when tapping a custom editButton in the navigation bar. When I create a custom editutton in the tableViewController the edit mode works as expected, but when I use the custom editButton in the navigation bar the setEditing bool value remains zero even when I setEditing to YES in the editButton selector. Here's the code:
ViewController.m
-(void)viewDidLoad {
self.editBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[self.editBtn setFrame:CGRectMake(0, 0, 40, 22)];
[self.editBtn addTarget:self action:#selector(goToToggleEdit:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *editButton=[[UIBarButtonItem alloc]initWithCustomView:self.editBtn];
self.navigationItem.rightBarButtonItem = editButton;
}
-(void)goToToggleEdit:(id)sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
TableViewController *tvc = [storyboard instantiateViewControllerWithIdentifier:#"aTableViewController"];
if(something==foo){
[tvc toggleEdit];
}
}
aTableViewController.h
#interface aTableViewController : UITableViewController <UITextFieldDelegate> {
IBOutlet UITableView *aTableView;
}
-(void) toggleEdit ;
#end
aTableViewController.m
-(void)toggleEdit {
[aTableView setEditing:YES animated:YES];
NSLog(aTableView.editing ? #"Yes" : #"No"); // --> logss 'No'.
if (aTableView.editing){
//do something
}
else {
//do something else
}
}
How can I efficiently trigger the edit mode in the tableViewController this way?
Edit
#Bagrat Kirakosian pointed out to me that my view hierarchy (Navigation Controller > View Controller (with containter) > Page View Controller (in container) > Table View Controller) might be the problem. I just want to create a Navigation Bar (with an edit button) that is fixed, therefore I can't embed the Table View Controller directly in a Navigation Controller.
Thanks.
UPDATE: Solution
I have accepted #sebastien's solution although both #sebastien's and #Bagrat's solution work great. #Bagrat's answer includes direct access to the Table View Controllers, while #sebastien's solution calls edit mode in the pageViewController. I think, considering the tricky hierarchy, the latter is a bit more secure.
Here is the code for my View Controller that totally work fine. be sure you configure your bar button in the right method of View Controller lifecycle. Also be sure that your #selector is properly implemented in your code.
In the same View Controller put these two blocks of code
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:#"edit_icon.png" ] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] style:UIBarButtonItemStylePlain target:self action:#selector(edit:)];
[rightBarButton setTintColor:[UIColor whiteColor]];
self.navigationItem.rightBarButtonItem = rightBarButton;
}
Afterwards you need also to put your edit selector
-(void)edit:(UIButton *)sender {
// Toggle edit by inverting current edit state
// Also in this block change your right bar button text or image
[self.tableView setEditing:!self.tableView.editing animated:YES];
}
UPDATE 1
After your comment we got to whole another question. You problem is not in the part where you try to call toggle edit. Your problem is the wrong hierarchy of controllers (Navigation Controller > View Controller > Page View Controller > Table View Controller). This might cause a problem. Try to change your controllers like this;
UINavigationController > UIPageViewController > UIViewController(s)
Also it's a good practice to have a UITableView in UIViewController rather than using really dead UITableViewController. Don't forget to connect your tableView IBOutlet (by the way you didn't need it in UITableViewController), also connect datasource and delegate to Files owner. In your MyTableViewVC.h file add this line
#interface MyTableViewVC : UIViewController <UITableViewDataSource, UITableViewDelegate>
After that all your calls will work fine.
UPDATE 2
After analyzing your entire structure I found a mistake that you do every time on the button click.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
tvc = [[TodolistTableViewController alloc] init];
When you call storyboard every time it's ok but when you do [[TodolistTableViewController alloc] init] you are RE-MAKING the same table view controller every time but not even adding it to your main view. As I told you, your tricky hierarchy might cause difficulties but it has a solution.
In your PageViewController.m make tv1 and tv2 properties in .h file, like so.
#property (strong, nonatomic) UITableViewController *tv1;
#property (strong, nonatomic) UITableViewController *tv2;
Then in the view controller file do this
-(void)toggleEdit:(id)sender
{
PageViewController *current = (PageViewController *)[[self childViewControllers] firstObject];
if ([current isKindOfClass:[PageViewController class]])
{
[((TodolistTableViewController *)[current tv1]) toggleEdit];
}
}
Answer includes all security checks and direct access to your table view controllers, because you might need to change other properties/call functions later.
Now in -(void)toggleEdit:(id)sender you don't re-create your views every time but you catch the ones you already have in your current View Controller.
Good Luck!
Ok, your issue here is that you are trying to access an embedded controller in a wrong way.
You are actually managing 2 differents PageViewController:
The one you generated through your storyboard
The other one you are initiating in your code further
That's why you can't reach the expected result.
First of all, add a new method to your PageViewController:
PageViewController.h:
- (void)editTableAtIndex:(int)index;
PageViewController.m:
- (void)editTableAtIndex:(int)index {
[[self viewControllerAtIndex:index] setEditing:YES];
}
Now, in your main ViewController, access the PageViewController by using childViewControllers:
-(void)toggleEdit:(id)sender
{
PageViewController *pvc = self.childViewControllers[0];
[pvc editTableAtIndex:0];
}
It should be editing your TodoListTableView:
(Please notice that I used [pvc editTableAtIndex:0];, instead you should be calling something like [pvc editTableAtIndex:_PageViewController_current_index_];)
I have an application that starts with a list of tasks and drills down through one or two list views to a final UIViewController. Due to the project requirements, these view controllers need to be created and navigated programmatically, not via segues in Interface Builder. I have accomplished this with single lists and regular view controllers, but one case has me stumped.
I currently have several UITableViewControllers in Interface Builder that point to other UITableViewControllers, basically a drill-down list. I'm unsure how to create a list item in my UITableViewController that creates another UITableViewController populated with list items I send it, and then navigates to it.
I need the UITableViewController to be generic, so I can create multiple drill-down lists using the same UITableViewController code.
Does this make sense? I feel like it should be a simple thing, but my brain just hasn't made the connection on how yet.
EDIT: Let me try to better illustrate my problem. My UITableViewController contains list items that are passed to it, and an array of objects associated with those items. The UITableViewController uses these objects to create the final UIViewController screen in most cases.
TableVC.h
#interface TableVC : UITableViewController <UITableViewDataSource, UITableViewDelegate>
//Menu items
#property NSMutableArray *itemList;
//Objects to pass to the detail ViewController
#property NSMutableArray *itemObjectList;
- (void)initWithList:(NSMutableArray *)items :(NSMutableArray *)objects :(NSString *)title;
#end
TableVC.m
NSMutableArray *items = [NSMutableArray arrayWithObjects:
NSLocalizedString(#"List Item 1",nil),
NSLocalizedString(#"List Item 2",nil), nil];
NSMutableArray *objects = [[NSMutableArray alloc]init];
MenuListObject *obj1 = [[MenuListObject alloc]init];
obj1.name =NSLocalizedString(#"Name",nil);
obj1.department=NSLocalizedString(#"Department",nil);
obj1.address=#"Address";
obj1.imgName=#"XXXYY.jpg";
obj1.menuIndex=0;
obj1.typeFlag=#"F";
...
[objects addObject:obj1];
[objects addObject:obj2];
TableVC *vc = [[TableVC alloc]init];
[vc initWithList:items :objects :NSLocalizedString(#"My Title",nil)];
[self.navigationController pushViewController:vc animated:YES];
However in some cases the list items don't go to a UIViewController. Instead they lead to another list, which then ends up at the UIViewController. I know how to create list items, but not a list item that leads to another UITableViewcontroller.
If there's a better way to handle all of this, I'm open to suggestions.
You can do this with segues aswell. Just make a "dummy segue" from a bar button item back to the view controller itself.
See this screenshot:
Then you can trigger this segue programmatically - i.e. when tapping a cell in a table view - to make an "infinite" stack of the same view controller.
And if you don't want segues. Just create the view controller programmatically, and push it manually. The same "reuse"-concept applies here.
Declare a class of type UITableViewController.
In it's .h file, declare an NSArray to hold the data.
In the .m file, implement the tableview delegate and data source methods, using the array as the data source.
In your calling tableViewController, in tableView:didSelectRowAtIndexPath:,
create a new instance of the tableviewController class,
then set it's array to the list of items you want to pass it,
and push it:
[self.navigationController pushViewController:_the_new_instance_ animated:YES];
I ended up using a third type flag in my TableViewController to denote when a list item should fire off a new list view rather than go to my destination UIViewController.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MenuListObject *obj = nil;
for (int i=0; i<self.itemObjectList.count; i++){
obj = [self.itemObjectList objectAtIndex:i];
if (obj.menuIndex == indexPath.row){
break;
}
}
if (obj!=nil)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
if ([obj.typeFlag isEqualToString:#"F"])
{
if (obj.url ==nil)
{
FacilityDetailVC *vc = [storyboard instantiateViewControllerWithIdentifier:#"FacilityDetail"];
vc.name=obj.name;
vc.department=obj.department;
...
[self.navigationController pushViewController:vc animated:YES];
}
else if ([obj.typeFlag isEqualToString:#"T"])
{
TextDetailVC *vc = [storyboard instantiateViewControllerWithIdentifier:#"TextDetail"];
vc.titleText=obj.titleText;
vc.descriptionText=obj.descriptionText;
vc.URL=obj.url;
[self.navigationController pushViewController:vc animated:YES];
}
//This is the part I added, to redirect to the UITableViewController
else if ([obj.typeFlag isEqualToString:#"L"])
{
TableVC *vc = [[TableVC alloc]init];
[vc initWithList:obj.listItems :obj.listObjects :obj.titleText];
[self.navigationController pushViewController:vc animated:YES];
}
}
I have a storyboard project and I would like to pass some data from a view into a tab bar controller, the information will be spread out between the tabs. After doing some research I found a very similar issue: iOS storyboard passing data navigationViewController but the only issue with this solution is that it was not transferring to a tab bar controller. I was wondering would I have to pass the data to each tab or can I pass it to the tab bar controller and then spread it from there? Thank you for your help in advance!
I am currently using the following; but, I get an error:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"FoodPage"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *nav = [segue destinationViewController];
FoodViewController *destViewController = (FoodViewController*) nav.topViewController;
destViewController.Foods = [foodArray objectAtIndex:indexPath.row];
}
}
In order to get a reference to your UINavigationController in your case, you have to do the following and specify the correct index to your tabBarController first:
UINavigationController *nav = [self.tabBarController.viewControllers objectAtIndex:<THE_INDEX_NUMBER_FOR_YOUR_NAVIGATION_CONTROLLER];
Once you have done so, then you retrieve a reference to your FoodViewController by specifying again the index number for it on your UINavigationController (i.e. if it's on top, then 0):
FoodViewController *destViewController = (FoodViewController*) [self.nav.viewControllers objectAtIndex:0];
Update:
Now that I got a better idea what you would like to achieve:
You are using UITabbarController in which your others controllers are embedded.
Scenario / Example Case:
Let say we had 2 view controllers, controller A and controller B, respectively, both are embedded in a UITabbarController.
What we want:
We are trying to change the text of a UILabel in controller B from controller A.
First, declare a property in controller B in .h:
#property(strong, nonatomic) UILabel *aLabelInControllerB;
Second, declare a a property (or ivar) in your controller A:
#property(strong, nonatomic) ControllerB *controllerB;
Since you are using UITabbarController you don't need to use segue, you could simply
get a hold of UITabbarController via self.tabBarController;
Question: "how would I know then when my tab bar controller is tapped and then change the text of the label in controller B?"
We do this:
Set controller A as the delegate of UITabbarController by:
In controller A .h, add:
#interface <Your_Controller> : UIViewController <UITabBarControllerDelegate>
In viewDidLoad of controller A:
self.tabBarController.delegate = self;
And in controller A .m, implement this method:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
self.controllerB = (ControllerB *) [tabBarController.viewControllers objectAtIndex:1];
//In our example here, we only have 2 view controllers (A and B)
//So, index 1 is where controller B resides.
self.controllerB.aLabelInControllerB.text = #"Hello!";
//This will change the text of the label in controller B
}
And as controller B appears, you will see that the text of the label will be changed to "Hello!"
Setting a NSString in controller B follows the same procedure.
Ex: self.controllerB.stringInControllerB = #"Hi from controller B!";
Hope that helps.
Update 2:
Segue'ing from table view cell to a tab bar controller? Oki.. Here is the solution. I am only using one cell in my example, so should it become desired that you would like to have more cells in the future, I would leave that up to you to adjust.
Let's take a look at the storyboard layout:
In storyboard, control drag from your cell to the tab bar controller.
Add a UINavigationController like in the picture.
In your UITableViewController .m:
Add 2 properties:
#property (strong, nonatomic) UITabBarController *myTabbarController;
#property (strong, nonatomic) YourFirstViewController *myFirstViewController;
Just a friendly reminder:
Remember to add:
self.tableView.delegate = self;
self.tableView.dataSource = self;
Add the following in your table view controller:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
self.myTabbarController = (UITabBarController*) [segue destinationViewController];
self.myFirstViewController = [self.myTabbarController.viewControllers objectAtIndex:0];
self.myFirstViewController.stringFromTableViewController = #"Hi from TableViewController!";
}
And in myFirstViewController, add 2 properties in .h:
#property (strong, nonatomic) NSString *stringFromTableViewController;
#property (strong, nonatomic) YourSecondViewController *secondViewController;
Like from the second edit above, have your first view controller to be still the delegate of UITabBarControllerDelegate and implement this method:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
self.secondViewController = (YourSecondViewController*) viewController;
self.secondViewController.aLabel.text = self.stringFromTableViewController;
}
Just like before, nothing needs to be changed in SecondViewController.
I ran this myself; should be good to go for your setup.
Enjoy.
It's also possible to access data from the TabBar within the TabBar's child viewcontrollers themselves, like so:
MyTabbarViewController *tabbar = (MyTabbarViewController *)self.tabBarController;
NSLog(#"%#", tabbar.data);
This way you only have to set the data in the TabBar like shown above, and then access it whenever you need it in a child view.
I need to pop up a quick dialog for the user to select one option in a UITableView from a list of roughly 2-5 items. Dialog will be modal and only take up about 1/2 of screen. I go back and forth between how to handle this. Should I subclass UIView and make it a UITableViewDelegate & DataSource?
I'd also prefer to lay out this view in IB. So to display I'd do something like this from my view controller (assume I have a property in my view controller for DialogView *myDialog;)
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:#"DialogView" owner:myDialog options:nil];
myDialog = [nibViews objectAtIndex:0];
[self.view addSubview:myDialog];
problem is i'm trying to pass owner:myDialog which is nil as it hasn't been instantiated...i could pass owner:self but that would make my view controller the File's Owner and that's not how that dialog view is wired in IB.
So that leads me to think this dialog wants to be another full blown UIViewController... But, from all I've read you should only have ONE UIViewController per screen so this confuses me because I could benefit from viewDidLoad, etc. that come along with view controllers...
Can someone please straighten this out for me?
There is no such thing as a view controller being on the screen; its view is on the screen. With that said, you can present as many views as you want on the screen at once.
I would create a new view and view controller. You would not make a UIView be a UITableViewDelegate, you make a UIViewController be a UITableViewDelegate. But instead of doing that manually, instead make your new view controller a subclass of UITableViewController, if you're using iPhone OS 3.x+. You can then present this view controller modally.
You probably want to give the user a chance to cancel out of the selection. A good way to do that is to wrap your new dialog view controller in a UINavigationController and then put a "Cancel" button in the nav bar. Then use the delegate pattern to inform the parent view controller that the user has made their choice so you can pop the stack.
Here's what the code will look like inside your parent view controller, when you want to present this option dialog:
- (void)showOptionView
{
OptionViewController* optionViewController = [[OptionViewController alloc] initWithNibName:#"OptionView" bundle:nil];
optionViewController.delegate = self;
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:optionViewController];
[self.navigationController presentModalViewController:navController animated:YES];
[navController release];
[optionViewController release];
}
Your OptionViewController .h will look like this:
#protocol OptionViewControllerDelegate;
#interface OptionViewController : UITableViewController
{
id<OptionViewControllerDelegate> delegate;
}
#property (nonatomic, assign) id<OptionViewControllerDelegate> delegate;
#end
#protocol OptionViewControllerDelegate <NSObject>
- (void)OptionViewController:(OptionViewController*)OptionViewController didFinishWithSelection:(NSString*)selection;
// or maybe
- (void)OptionViewController:(OptionViewController*)OptionViewController didFinishWithSelection:(NSUInteger)selection;
// etc.
#end
Your OptionViewController.m will have something like this:
- (void)madeSelection:(NSUInteger)selection
{
[delegate OptionViewController:self didFinishWithSelection:selection];
}
Which has a matching method back in your original view controller like:
- (void)OptionViewController:(OptionViewController*)OptionViewController didFinishWithSelection:(NSUInteger)selection
{
// Do something with selection here
[self.navigationController dismissModalViewControllerAnimated:YES];
}
There are plenty of examples throughout Apple's sample source code that follow this general pattern.
I have a UITableViewController within a UIViewController. While this table viewcontroller was the only one involved, it was pushing views just fine when the user would tap a row. However, ever since I moved it to be one of two contained within the UIViewController, the taps of rows suddenly do nothing.
I've tried searching around and I'm not the first to run into this problem, but none of the answers fit my circumstances or the questions have no working answers. That link was the closest I found, but I'm not using storyboards -- I'm using separate XIBs.
So how do I push a new view from a viewcontroller within a viewcontroller?
To recap:
Here is what I had, and it worked fine in taking users to a new screen!
// Normal table behavior, as illustrated by [another question][2].
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SomeView *detailViewController = [[SomeView alloc] initWithNibName:#"SomeView" bundle:nil];
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
}
Now I have the viewcontroller as a property in a view -- and the above code, which is in the file for the tableviewcontroller and not at the "main" view, doesn't cause a new screen to appear anymore!
Thanks for the comments! Here's some code to clarify my scenario.
The controllers within a controller. This is a file from a test project I've been using to test the concept out. In this case, I have a tableview controller within a tableview controller.
#interface SimpleTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
// This is the controller within the controller
#property IBOutlet SecondTableViewController *secondTableController;
#property IBOutlet UITableView *secondTable;
My SecondTableViewController has this fun bit.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
UIViewController *detailViewController = [[UIViewController alloc] initWithNibName:#"SimpleNonTableViewController" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[manualViewControllerParent.navigationController pushViewController:detailViewController animated:YES];
}
The view that the user interacts with is hooked up to SimpleTableViewController. In this way, SecondTableViewController is "within" SimpleTableViewController. Feel free to comment if you'd like more details!
I've put my test/concept project on github. https://github.com/hyliandanny/TableViewCeption
You need to use a custom container controller to do what you want. It would be easiest if you used a storyboard, but you can do it in code with xibs as well. The outer controller should be a UIViewController, not a table view controller. You can do something like this (in the outer controller):
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UIViewController *detailViewController = [[UIViewController alloc] initWithNibName:#"SimpleNonTableViewController" bundle:nil];
[self addChildViewController:detailViewController];
detailViewController.view.frame = set the frame to what you want;
[self.view addSubview:detailViewController.view];
[detailViewController didMoveToParentViewController:self];
}
You should read up on Apple's documentation for custom container controllers.
What you need to make sure:
Your UITableView delegate is hooked up to your controller. Otherwise it wouldn't call didSelectRow. You can do this in xib or in viewDidLoad method.
Your self.navigationController is not nil
Your detailViewController is not nil
I also think that what you mean is you have UITableView inside your UIViewController. UITableView is only the view, whereas UITableViewController is a controller. You can't have a controller inside another controller.