I want to have a UITableViewController controlling my TableView.
Where (and how) should I call init on the UITableViewController?
EDIT
Here's my current code inside my prepareForSegue method:
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
ReccyTableViewController *tableViewController = (ReccyTableViewController *)[[navigationController viewControllers] objectAtIndex:0];
ProjectDataController *aDataController = [[ProjectDataController alloc] init];
[tableViewController setDataController:aDataController];
[self presentViewController:tableViewController animated:YES completion:nil]; //Fails here
EDIT #2
Here's what I did in the end:
I scrapped trying to init the datacontroller in the prepareForSegue method and did it in the viewDidLoad method instead:
- (void)viewDidLoad
{
[super viewDidLoad];
_dataController = [[ProjectDataController alloc] init];
}
this may help you
read apple official docs
You should call it from the point of your previous controller from where you want to add/push this tableViewController.
Related
I want to call this method:
- (void)getUserFriendTargetDialogRequest {
currentAPICall = kAPIFriendsForTargetDialogRequests;
[self apiGraphFriends];
}
from this conditional statement that's in another viewcontroller:
if (idx == 2) {
NSLog(#"you touched menu 2");
APICallsViewController *apiViewController = [APICallsViewController alloc];
[self.navigationController pushViewController:apiViewController animated:YES];
}
can anyone help with the syntax on this?
thanks so much
First, you probably also want to init your APICallsViewController via:
APICallsViewController *apiViewController = [[APICallsViewController alloc] initWithNibName:nil bundle:nil];
Then if that getUserFriend... is a method of APIViewController, you can do this:
[apiViewController getUserFriendTargetDialogRequest];
However, since you aren't passing any arguments in from your other view controller, you might consider calling it in the init method, or the viewDidLoad method of APICallsViewController.
OtherViewController *viewController = [[OtherViewController alloc]
init];
[viewController methodName];
[viewController release];
1>Just alloc the class in which the method is and then call it through object of that class.
ViewControllWithMethod *view=[ViewControllWithMethod alloc]]init];
[view getUserFriendTargetDialogRequest];
2>Instead of instance method you can make it as class method then you will be able to call it through className.getUserFriendTargetDialogRequest
I have a class called CataloguesEtTarifsPDFViewController which displays a tableView.
Now, inside this class I wanna create a UINavigationController and set the root of the UINavigationController this class:
Here is what I did:
CataloguesEtTarifsPDFViewController.h
UINavigationController *navigationController;
in the implementation file
CataloguesEtTarifsPDFViewController.m
- (void)viewDidLoad
{
CataloguesEtTarifsPDFViewController *catalog =[[CataloguesEtTarifsPDFViewController alloc] init];
loadingView.hidden=YES;
navigationController = [[UINavigationController alloc] initWithRootViewController:catalog];
}
When I click on the table cell I do this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
WebViewController *webViewController = [[WebViewController alloc] init];
[self.navigationController pushViewController:webViewController animated:YES];
[navigationController release];
}
But when I run and click on the tableView nothing happens...not view is showed up!!!Where am I going wrong?
IMPORTANT: I don't have a delegate file.Only CataloguesEtTarifsPDFViewController.h CataloguesEtTarifsPDFViewController.m and CataloguesEtTarifsPDFViewController.xib.
EDIT:
- (IBAction)showViewCataloguesEtTarifsPDF:(id)sender{
// Remove view to middleView
[mainMenuViewController removeViewsToMiddleView];
// create view controller
cataloguesEtTarifsPDFViewController = [[CataloguesEtTarifsPDFViewController alloc] init];
cataloguesEtTarifsPDFViewController.mainMenuViewController = mainMenuViewController;
// hide/show header button
[mainMenuViewController.headerViewController showMainMenuButton];
// highlight footer tabbar button
[mainMenuViewController.footerViewController.footerTabBar setSelectedItem:mainMenuViewController.footerViewController.footerTabBarItemMyAudi];
UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:cataloguesEtTarifsPDFViewController];
[self presentModalViewController:navigationController animated:YES];
}
You should probably read this: http://www.iosdevnotes.com/2011/03/uinavigationcontroller-tutorial/
Or this: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007457-CH1-SW1
Or watch this: http://peepcode.com/products/iphone-view-controllers-part-i
That'll give you the basics and you'll be well equipped to answer your question and fix your code :)
PS: You don't have to explicitly create and set a UINavigationController in your view controller. If the view controller is embedded within a navigation controller, the navigationController property of your view controller instance will automatically find it and return it.
What you're doing in viewDidLoad is wrong.
Wherever you are showing the CataloguesEtTarifsPDFViewController, you should wrap it in a UINavigationController there and show the UINavigationController instead.
This will make sure the navigationController property of UIViewController will be set.
In your tableView:didSelectRowAtIndexPath: method you should release the webViewController variable instead of the navigationController property.
The other day I asked about using a UINavigationController as a child of a UIViewController. I got that working via the answer. Now what I'm trying to do is push a controller onto the nav stack. When a table cell is touched, I do the following:
- (void) showSetup {
NSLog(#"Showing Setup");
SetupViewController *controller = [[SetupViewController alloc]initWithNibName:#"SetupViewController" bundle:nil];
self.setupViewController = controller;
self.setupViewController.title = #"Setup";
[self.navigationController pushViewController:self.setupViewController animated:YES];
[controller release];
}
I can see the log statement in my console, but the view never changes. Am I missing something?
Hmmm, well it's a bit tricky without knowing the details of your implementation -- I assumed that you implemented your navigation controller as in the linked article. Also although you give no details it sounds like you've added a table view controller somewhere along the line, so I made the UIViewController conform to the UITableView protocols to handle everything in one place:
#interface SOViewController : UIViewController<UITableViewDelegate,UITableViewDataSource > {
UINavigationController* navController;
}
- (IBAction) pushMe:(id)sender;
#end
I dropped a button on the SOViewController's view in IB and wired the pushMe: action to it. I also created another UIViewController-based class called JunkController and dropped a "Junk" label on it's view in IB -- that's all I did in IB. In the SOViewController's viewDidLoad:
navController = [[[UINavigationController alloc] init] retain];
navController.navigationBar.barStyle = UIBarStyleBlackOpaque;
navController.toolbarHidden = YES;
UITableViewController* tvController = [[UITableViewController alloc] init];
UITableView* tv = [[UITableView alloc] init];
tvController.tableView = tv;
tv.delegate = self;
tv.dataSource = self;
[navController setViewControllers:[NSArray arrayWithObject:tvController]];
In the pushMe: action implementation:
[self presentModalViewController:navController animated:YES];
Implemented the tableView delegate and datasource methods; for selection:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"row selected");
JunkController* junk = [[JunkController alloc] initWithNibName:#"junkcontroller" bundle:nil];
[navController pushViewController:junk animated:YES];
[junk release];
}
This should yield an app that surfaces a screen with a "Push me" button. When that button is pressed you should get an animated modal navigation-based table view -- mine had one row in it that contained a label "select me". Touching this row should animate the junk controller into view.
There is no need to make setupViewController a declared property in this view controller. Also, I could be mistaken but I thought "controller" was a reserved name in Cocoa, I'd change that name. So make sure you have registered with the UITableViewDelegate and use - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath to hook into and push your new view controller as follows:
SetupViewController *detailViewController = [[SetupViewController alloc] initWithNibName:#"SetupViewController" bundle:nil];
detailViewController.title = #"Setup";
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
Goodluck!
UIViewController *theController = [[HelpViewController alloc] initWithNibName:#"HelpView" bundle:nil];
[self.navigationController presentModalViewController:theController animated:TRUE];
Here's my code for showing my view. I know I can use app delegate variables, but it would be neater is I could pass a parameter in somehow, ideally using an enum. Is this possible?
Just create a new init method for your HelpViewController and then call its super init method from there...
In HelpViewController.h
typedef enum
{
PAGE1,
PAGE2,
PAGE3
} HelpPage;
#interface HelpViewController
{
HelpPage helpPage;
// ... other ivars
}
// ... other functions and properties
- (id)initWithNibName:(NSString*)nibName bundle:(NSBundle*)nibBundle onPage:(HelpPage)page;
#end
In HelpViewController.m
- (id)initWithNibName:(NSString*)nibName bundle:(NSBundle*)nibBundle onPage:(HelpPage)page
{
self = [super initWithNibName:nibName bundle:nibBundle];
if(self == nil)
{
return nil;
}
// Initialise help page
helpPage = page;
// ... and/or do other things that depend on the value of page
return self;
}
And to call it:
UIViewController *theController = [[HelpViewController alloc] initWithNibName:#"HelpView" bundle:nil onPage:PAGE1];
[self.navigationController presentModalViewController:theController animated:YES];
[theController release];
I generally just have certain variables in my UIView, which I set from the parent view. To pass variables back, I make use of the function:
[[[self.navigationController viewControllers] lastObject] setFoo:foo];
Define a setter for the parameter in HelpViewController and change your code to:
HelpViewController *theController = [[HelpViewController alloc] initWithNibName:#"HelpView" bundle:nil];
[theController setSomeValue:#"fooBar"];
[self.navigationController presentModalViewController:theController animated:YES];
I'm using the Kal calendar. For the code shown below I'm referring to the Holiday example. In this example the allocation and initialization of Kal is done in the applicationDidFinishLaunching in the AppDelegate. The UITableViewDelegate protocol (e.g. didSelectRowAtIndexPath) is also positioned in the AppDelegate class.
The AppDelegate:
#import "HolidayAppDelegate.h"
#import "HolidaySqliteDataSource.h"
#import "HolidaysDetailViewController.h"
## Heading ###import "Kal.h"
#implementation HolidayAppDelegate
#synthesize window;
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
kal = [[KalViewController alloc] init];
kal.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:#"Today" style:UIBarButtonItemStyleBordered target:self action:#selector(showAndSelectToday)] autorelease];
kal.delegate = self;
dataSource = [[HolidaySqliteDataSource alloc] init];
kal.dataSource = dataSource;
// Setup the navigation stack and display it.
navController = [[UINavigationController alloc] initWithRootViewController:kal];
[window addSubview:navController.view];
[window makeKeyAndVisible];
}
// Action handler for the navigation bar's right bar button item.
- (void)showAndSelectToday
{
[kal showAndSelectDate:[NSDate date]];
}
#pragma mark UITableViewDelegate protocol conformance
// Display a details screen for the selected holiday/row.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Holiday *holiday = [dataSource holidayAtIndexPath:indexPath];
HolidaysDetailViewController *vc = [[[HolidaysDetailViewController alloc] initWithHoliday:holiday] autorelease];
[navController pushViewController:vc animated:YES];
}
#pragma mark -
- (void)dealloc
{
[kal release];
[dataSource release];
[window release];
[navController release];
[super dealloc];
}
#end
I don't want to put this into the AppDelegate, because there could be some overlapping code with other views. It should be a separate "component" which I can call and put on the stack.
In my navigation based project I have a main view, the RootViewController. From there I want to push the Kal view on the stack. Currently I'm pushing an additional ViewController on the stack. In the viewWillAppear method from this ViewController I do the things shown in the code above. The following problems appear:
Navigation back has to be done two times (one for the Kal calendar, one for my created view)
Navigation to my main view is not possible anymore
In the moment I don't know where to put this code. So the question is where to put the methods for allocation/initialization as well as the methods for the UITableViewDelegate protocol.
Solution:
if (kal == nil) {
kal = [[KalViewController alloc] init];
kal.navigationItem.title = NSLocalizedString(#"Timetable",#"");
kal.delegate = self;
self.dataSource = [[[MyDataSource alloc] init] autorelease];
kal.dataSource = dataSource;
}
[[self navigationController] pushViewController:kal animated:YES];
I've done the initialization in my RootViewController. This isn't the best solution, but I didn't found another one.
Suggest to read the SimpleEKDemo example from Apple.