iphone UITableVIew (Navigation-based ) - iphone

I'm working on a navigation-based application.
My rootViewController contains 3 cells
-When the first one is pressed a UIViewController is pushed (THIS WORKS)
-The problem is with the 2nd and 3rd cells that are supposed to push a UITableViewController
The app is running with no errors and it is NOT crashing at all, but when i navigate to the tableview, an empty table is viewed with no elements in it.
Is the problem with this part of the code?? :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *detailViewController = [[UIViewController alloc] initWithNibName:#"Introduction" bundle:nil];
detailViewController.title=#"Introduction";
UITableViewController *myPictures = [[UITableViewController alloc] initWithNibName:#"Pictures" bundle:nil];
myPictures.title=#"Pictures";
UITableViewController *myImages = [[UITableViewController alloc] initWithNibName:#"ImagesViewController" bundle:nil];
myImages.title=#"Images";
// Pass the selected object to the new view controller.
if (0 == indexPath.row)
[self.navigationController pushViewController:detailViewController animated:YES];
if (1== indexPath.row)
[self.navigationController pushViewController:myPictures animated:YES];
if (2== indexPath.row)
[self.navigationController pushViewController:myImages animated:YES];
[detailViewController release];
[myPictures release];
[myImages release];

What you're doing it very wrong (apart from your original problem). Why are you instantiating each view controller and then only using the one based on the current 'cell selection'? This will slow your app down depending on how much time it would take to load each of these separate views. You should only instantiate the relevant view controller inside the "if (indexPath.row == 2) {" block.
Apart from that there are many things wrong about your approach. What you are doing will never work since instantiating a generic UITableViewController (even if you supply your own nib) will obviously only show you an empty view. You need to have a class of your own which the nib is tied to as a delegate which will then supply the TableView with data.
I believe when you created these nib files (for example "Pictures") xcode also give you a 'PicturesViewController.h and PicturesViewController.m" files? If so, you need to write the appropriate code there and ensure the Tableview in the "Pictures" nib file has its 'datasource' and 'delegate' set to 'PicturesViewController'. Then when you want to show that view do this instead:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 1) {
...
} else if (indexPath.row == 2) {
PicturesViewController *myPictures = [[PicturesViewController alloc] initWithNibName:#"Pictures" bundle:nil];
[self.navigationController pushViewController:myPictures animated:YES];
[myPictures release];
}
}

Related

UINavigationController with two copies of the same view controller on stack

I am using a UINavigationController to push a UIViewController onto the stack, then when the user selects a row in the table view I allocate a new version of the view controller and push it onto the stack this works fine but then when I start pressing the back button the NSMutableArray that I am using to store the information seems to be keeping the value from the view controller that was just poped from the stack.
Here is the method that is pushing the new onto the stack:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (indexPath.section == 1) {
if (hasLoadedResponses && [responses count] == 0) {
return;
}
VideoDetailViewController_iPhone *nextView = [[VideoDetailViewController_iPhone alloc] initWithNibName:#"VideoDetailViewController_iPhone" bundle:nil withVideoArray:[responses objectAtIndex:indexPath.row]];
nextView.navController = navController;
[navController pushViewController:nextView animated:YES];
[nextView release];
}
}
I'm sure there is something stupid I am missing, but can't seem to find it right now.
Assuming the mutable array is [responses objectAtIndex:indexPath.row] because is the only value you pass to the new pushed view controller, then if you are modifying it in you have to take in account that is the same object and so modifications are shared.
You can write:
. withVideoArray:[NSMutableArray arrayWithArray:[responses objectAtIndex:indexPath.row]];
As I said, I assume that object is the mutable array of your problem.
Another smarter solution is defining the property you use to store the mutable array as 'copy' instead of 'retain'.

How can I move to another view controller when the user clicks on a row?

I am new to iPhone development, and I want to move to another page when the user clicks on a particular row. So, if they click on first row, I want the page to redirect to the first view controller, and so on. Each row has its own view controller.
first of all you don't need to set different view controller for each row (unless you have a very good reason for doing that).
the correct way is to set 1 view controller that will fit all the cells in the raws and change its data according to the selected row.
the way you do that is:
in the - DidSelectRowAtIndexPath function in your implementation file you shuld:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//allocate your view controller
DetailedViewController *detailedViewController = [[DetailedViewController alloc] init];
//send properties to your view controller
detailedViewController.property1 = someProperty1;
detailedViewController.property2 = someProperty2;
//push it to the navigationController
[[self navigationController] pushViewController:detailedViewController animated:YES];
[detailedViewController release];
}
i do recommend that you will start by using apple examples, they are great and there are a lot of them :
http://developer.apple.com/library/ios/#samplecode/TableViewSuite/Introduction/Intro.html%23//apple_ref/doc/uid/DTS40007318
Good luck
#kashyap in didSelectRowAtIndexPath delegate of the UITableView you have to check the conditions that on which indexPath you are clicking and open the viewControllers you had made accordingly
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here -- for example, create and push another view controller.
FirstViewController *firstViewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
switch (indexPath.row) {
case 0:
[self.navigationController pushViewController:firstViewController animated:YES];
[firstViewController release];
break;
case 1:
[self.navigationController pushViewController:secondViewController animated:YES];
[secondViewController release];
break;
}//Likewise do for the no of rows you have in your `UITableView`
Hope you get my point.....Good Luck!
Dig into the docs:
http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/TableView_iPhone/ManageSelections/ManageSelections.html#//apple_ref/doc/uid/TP40007451-CH9-SW6
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
switch (indexPath.row) {
case "X"
// Allocate the viewController
[navigationcontroller.pushViewController:"yourviewcontroller" animated:YES];
[release "yourviewcontroller"];
break;
default:
break;
}
}
EDIT: Didn't realize of what you're trying. As shani said, you should not create a viewcontroller for each row if there is no need to. Try changing the datasource for each row but using the same viewcontroller. So forget this implementation.
Easy:
Create and push your view controller in this delegate function:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
It sounds like using a UINavigationController is what you want.
You then push your "first view" on to the navigation controller's stack from the table view, e.g., from you UITableView delegate:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
// indexPath.row == 0
FirstViewController* firstVC = [[FirstViewController alloc] initWithNibName...];
[self.navigationController firstVC animated:YES];
[firstVC release];
...
}
This was the one the things that I got problem when I first start. Here is my code that I use for this.
In subviewcontroller I have my own constructor like
-(id)initWithName:(NSString*)naMe
{
name=naMe;
return self;
}
And in didSelectRowAtIndexPath Delegate method Of UITableView. I alloc it
MyListView mylistview=[[MyListView alloc] initWithName:#"name"];
[self.navigationController pushViewController:mylistview animated:YES];
[mylistview release];
NSInteger row = indexPath.row;
UIViewController *newFrontController = nil;
if (row == 0)
{
YourViewController *yourViewController = [[YourViewController alloc] initWithNibName:#"YourViewController" bundle:nil];
newFrontController = [[UINavigationController alloc] initWithRootViewController:peopleViewController];
[self.navigationController setNavigationBarHidden:YES];
} else if(row == 1){
//do your code
}
do this in didSelectRowAtIndexPath in tableView.
You can move to another page when user tap on row by simply making segue by "Control Drag" from cell to ViewController and make segue type "Push".

Load a particular NIB based on tableview selection

I have an initial table view that I created as the initial menu within my app. Obviously each option will access something different including NIBs. Part of the constants for the menu options is the NIB. When each option is pulled from a PLIST, I also include which NIB I would like to be called upon.
Am I missing something or am I just going the wrong way entirely?
Right now a selection does nothing.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableString *targetnib = [[self.menuoptions objectAtIndex:indexPath.row] objectForKey:NIB_KEY];
if (targetnib == #"HospitalDirectoryViewController") {
HospitalDirectoryViewController *hospitalDirectoryViewController = [[HospitalDirectoryViewController alloc] initWithNibName:#"HospitalDirectoryViewController" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:hospitalDirectoryViewController animated:YES];
[hospitalDirectoryViewController release];
}
if (targetnib == #"PhysicianDirectoryViewController") {
PhysicianDirectoryViewController *physicianDirectoryViewController = [[PhysicianDirectoryViewController alloc] initWithNibName:#"PhysicianDirectoryViewController" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:physicianDirectoryViewController animated:YES];
[physicianDirectoryViewController release];
}
}
Try using [targetnib isEqualToString: #"TheNibName"]. In your posted code, you're comparing pointers, not the text.

Code is exectuting but the view is not loading when called form a function?

I am doing a book kinda application using a viewBased application. The mainView acts as the backgroundView for loading pages. Each page is a different view and have its own nib. When i swipe on a page(actually on the mainView which have loaded the current view/page), that page will be removed and the next/previous page will be added.
[currentPage.view removeFromSuperview];
[self.view insertSubview:nextPage.view atIndex:0];
I have added a popoverController with a barbutton in this mainView. Its intialized with a tableviewController class named popClass. PopClass is another UITableViewController class which will act as the parent for the popViewController.
self.myPopController = [[PopController alloc] initWithStyle:UITableViewStylePlain];
self.myPopOverController = [[UIPopoverController alloc] initWithContentViewController:myPopController];
When I select certain row in the popover, I want the backgroundview(mainView) to load the page corresponding to the number of the row.
For that I have written a function in bookView(mainView) Controller class. And is calling it from the popOver's parent class when i select certain row.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger toPageNumber = indexPath.row + 1;
[viewController changeToPage:toPageNumber];
}
Function and the lines of code are executing but nothing is happening. Even the log lines are printed but no action takes place. The code is the same for removing a page and adding another page which is working successfully when i swipe the view/page.
What is the problem? OR is there anyother way to make the view change in mainView by using the popover?
You need to have refernce of the background view controller in the popover controller.
In the PopController controller you should have a delagate like:
#interface PopController: UITablViewController{
//// other varibales;
id delegate;
}
#property (nonatomic, retain) id delgate;
Now from the class in which you are showing the popovercontroller
you should add this line:
[myPopController setDelegate:self];
Then you can easily acces any method of the main view controller class. By using
[delegate callTheRequiredMethod];
Hope this helps.
Thanks,
Madhup
It's hard to tell what's going wrong without looking at the code. That said, here's what I'd do:
(1) When a row is selected in mainView, present the popoverController modally:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
PopoverViewController *vc = [[PopoverViewController alloc] init];
[self.navigationController presentModalViewController:vc animated:YES];
[vc release];
}
(2) When something changes in the popoverController, for example a row is selected, set a value in the parentViewController (which should be the MainView):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.parentViewController.value = someValue;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
(3) Dismiss the popoverController where-ever you choose by calling:
[self dismissModalViewControllerAnimated:YES]`

How do I create a UIViewController programmatically?

I am working in a app where i have data in UITableView. It is like a drill down application. User will click on a row and will go to next page showing more records in a UITableView. But problem in my case is that i dont know upto how many level user can drill. The number of levels are not fixed. So now i am thinking to create and add the viewcontrollers programmatically. Is it possible?? if yes how?
thanks in advance.
UIViewController *controller = [[UIViewController alloc] init];
controller.view = whateverViewYouHave;
Do you have your own view controller that you coded? In that case you probably don't need to set the view property as it has been set in IB if that is what you used. When you have your controller you can push it onto the navigationController or view it modally etc.
UIViewControllers are always created programmatically. It sounds like you just need to have the same class for each level of view controller, e.g.:
//CoolViewController:UITableViewController
//CoolViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (!self.isAtTopLevel) {
CoolViewController *cvc = [[CoolViewController alloc] initWithRecord:[self.records objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:cvc animated:YES];
[cvc release];
} else {
//do something else
}
}
In this case, thingies would be some sort of recursive NSArray (i.e. an array of arrays).