Show different view on navigation controller when data is empty using storyboard - objective-c

I have a navigation controller with a tableview controller as the first controller, however when the database is empty I want to show the user a view that asks the user for some information to fill the database and show it in the navigation controller instead of the view assigned in storyboard, I guess I would have to do this programmatically, but I'm new to iphone development and honestly dont know where to start.

Here's how you can do it. Create a new scene in your storyboard for your view controller where the user will submit the info (let's say it's called CollectInfoViewController). Then create a modal segue from your tableview controller to the CollectInfoViewController. In the Attributes Inspector, set the Identifier property of the segue to "CollectInfo" so you can identify it later.
Then when your tableview controller's viewDidLoad method runs, ask the table view delegate whether there are any rows to show. If there are not, programmatically perform the segue to your CollectInfoViewController.
- (void)viewDidLoad
{
[super viewDidLoad];
if ([self.tableView.dataSource tableView:self.tableView numberOfRowsInSection:0] == 0) {
[self performSegueWithIdentifier:#"CollectInfo" sender:self];
}
}
In your CollectInfoViewController, once the user has entered the information and you have stored it in your database then you can call the following from within CollectInfoViewController to dismiss that view. This will return the user to the tableview.
[self dismissModalViewControllerAnimated:YES];
Finally, back in your tableview controller, you might need to reload your table with the new data that's been collected. You can do that in viewWillAppear, which will be called when the modal view controller is dismissed.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView reloadData];
}

Related

Hide MasterViewController when clicking a button

I have a Master/Detail application and everything works right..i added a button with the purpose of taking me to another tableViewController. I need, when i go to that table view controller, to hide permanently the master view controller from portrait and landscape mode.So to recapitulate, i am in a newly created table view controller independent from the original Detail View Controller, and i need to hide permanently the master view controller when this button is clicked and the new TableViewController is loaded..How can i do it ? I tried to use a MGSplitViewController but i got lost using it..i'm a newb in Xcode development. Any help will be highly appreciated.Update 1:My problem is not with the Detail View Controller...in the Detail ViewCOntroller i have added a button that will take me to another tableviewcontroller...now when i load that i need to force the masterviewcontroller to stay hidden how can i do it?
Once you configure your detail view controller, you need to need to dismiss the popover controller.
if (self.popoverController) {
[self.popoverController dismissPopoverAnimated:YES];
}
If your detail view controller doesn't already have a property to hold the UIPopoverController, you can capture it by implementing these delegate methods for UISplitViewControllerDelegate
- (void)splitViewController:(UISplitViewController *)iSplitViewController
willHideViewController:(UIViewController *)iViewController
withBarButtonItem:(UIBarButtonItem *)iBarButtonItem
forPopoverController:(UIPopoverController *)iPopoverController {
self.popoverController = iPopoverController;
}
- (void)splitViewController:(UISplitViewController *)iSplitViewController
willShowViewController:(UIViewController *)iViewController
invalidatingBarButtonItem:(UIBarButtonItem *)iBarButtonItem {
self.popoverController = nil;
}

Should I use the same detail ViewController to work both modally and when pushed?

This seems to be the patten used throughout Apples applications; Creation of a new record is done through a modal View which needs to be saved or canceled to continue, and editing a record is done through a view pushed onto the navigation stack.
It doesn't seem right to be basically duplicating my ViewController for 'add' and 'edit' but there are several differences in how pushed and modal ViewControllers work which complicate things.
How should I be doing this so it can cover both bases?
-
Differences include.
When pushed onto the stack the navBar appears at the top of the View and can be configured to contain the cancel/save buttons. When presented modally this is not the case so to duplicate the interface a toolbar needs to be created separately and close/save buttons added to this instead.
When dismissing a pushed view we send a message to the navigation controller [self.navigationController popViewControllerAnimated:YES];, when dismissing a modal view we send a message to self [self dismissModalViewControllerAnimated:YES];
You could add the UIToolbar in InterfaceBuilder, and then just hide it in viewDidLoad when self.navigationController is not nil.
As for dismissing, you could have something like:
- (void)didCancel {
[self.navigationController popViewControllerAnimated:YES] || [self dismissModalViewControllerAnimated:YES];
}
This will shortcircuit if your viewcontroller is part of a navigationcontrol, and use dismissModalViewControllerAnimated otherwise.
This should work for your cancel button. For your save button, it is useful to call some sort of delegate method such as:
- (void)didSave {
// do your saving juju here
if([self.delegate respondsToSelector:#selector(viewController:didSave:]) {
[self.delegate viewController:self didSave:whatJustGotSaved];
}
[self.navigationController popViewControllerAnimated:YES]; // noop if currently modal
}
In the delegate's implementation then, you can put:
- (void)viewController:(UIViewController*)viewController didSave:(NSObject*)whatJustGotSaved {
// do stuff with parameters
[self.modalViewController dismissModalViewControllerAnimated:YES]; // noop if not modal
}

UISplitViewController not calling delegate methods while pushing new detailView

I setup a storyboard based on the Master-Detail Application, embed the detail view in a navigation controller, and add a new table view controller object which I will use as a second detail view controller.
I then push the new detail view controller with the following code (instead of a segue because I am pushing both a root view and a detail view controller at the same time. Only the detail view code is shown).
// Push the detailView view controller:
NewClass *newViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"test"];
newViewController.navigationItem.hidesBackButton = YES;
self.splitViewController.delegate = newViewController;
[self.detailViewController pushViewController:newViewController animated:YES];
This works perfectly, EXCEPT that the splitView delegate methods are never called before or after the push. If I do this while in portrait mode, after it pushes the detailViewController, the button to drop down the masterView popover does not show up UNTIL I rotate to landscape mode and then back to portrait mode.
How can I cause the willHideViewController/willShowViewController split view controller delegate methods to be called or manually cause them to be called?
So from what I found, it doesn't call the method because the orientation hasn't changed.
What you have to do is to pass the button from the presenting view controller since it's already tied to the popover like this:
if(self.navigationItem.leftBarButtonItem != nil) {
newViewController.navigationItem.leftBarButtonItem = self.navigationItem.leftBarButtonItem;
}
// Push the newViewController

UITableView delegate not called when UIViewController is popped

I have a view controller that contains a UITableView. When the view controller gets pushed onto the stack, the table view delegate methods get called and it populates the table.
Then I push another view controller onto the one that contains the table view. What I would like to make happen is that - when the second view controller gets popped and I return to the previous view controller, those uitableview delegate methods get called again (so as to repopulate the table).
In other words, how do you repopulate a uitableview when popping to a view controller.
Thanks
In viewDidLoad or viewDidUnload, viewWillAppear, viewWillDisappear (whichever of these is right for your situation) you can put [myTable reloadData];:
// If you can include some code it would help as I am a bit uncertain
// about exactly what you are trying to do from the question but
// you should use whichever of these is correct for project:
- (void)viewDidLoad {
[super viewDidLoad];
[myTable reloadData];
}
- (void)viewDidUnload {
[myTable reloadData];
}
- (void)viewWillAppear {
[super viewWillAppear];
[myTable reloadData];
}
- (void)viewWillDisappear {
[super viewWillDisappear];
[myTable reloadData];
}
What you should do is add a [self.tableView reloadData] (or whatever your table variable is) call inside the viewWillAppear method of its view controller. This will cause the table view to be reloaded both when being pushed (as it does now) and when other view controllers are popped to reveal it.

Split-View Based Application - Navigation in RootViewController

Solved
Hey all,
I'm currently working on a Split-View Based Application for iPad. I want the Root View Controller to navigate to another TableView, and from there, the users can select the appropriate row and display the information in the DetailViewController. I managed to code the navigation part in (The Root View Controller navigates to another table instead of displaying information instantly to the Detail View Controller), but I can't seem to display information based on the user's TableView selection.
The Hierarchy of Selection is as follows:
RootViewController -->Select Row in Root View Controller --->Navigate to TableView-->Select Row from TableView-->Display in Detail View Controller
Any ideas?
Thanks.
Here was my solution, partly.
In didSelectRowAtIndexPath (delegate is my app delegate singleton):
[delegate setDetailItem:newFile];
setDetailItem:
- (void)setDetailItem:(id)newDetailItem
{
if (detailItem != newDetailItem)
{
[detailItem release];
detailItem = [newDetailItem retain];
}
detailViewController.detailItem = self.detailItem;
[self.detailViewController configureView];
}
the detailViewController has an (id) variable detailItem which i set from the row i selected. then i configure my detailview as needed based on this item. So there is a start for you.