Hide MasterViewController when clicking a button - objective-c

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;
}

Related

How to hide masterView for UISplitViewcontroller in IOS8

All,
I have met a problem with new UISplitViewcontroller in IOS8 for iPad. I have a UITableView in the storyboard in the detailViewcontroller and on clicking the cell, I should go to the another view called "detailinfo". I am current using a "show" segue.
However, the current segue just push on the right part. I wanna it show fullscreen , but I dont know how to make it, I tried using preferredDisplayMode property of the splitViewController , the result is it just hide the master view but didnt resize the detailView. I dont wanna using present as modal.
current way I am doing is
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([[segue identifier]isEqualToString:#"showStudentDetail"]){
if(self.traitCollection.horizontalSizeClass != UIUserInterfaceSizeClassCompact){
UISplitViewController *splitViewController = (UISplitViewController *)self.navigationController.parentViewController;
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
}
}
}
and in viewDidAppear, using
- (void)viewDidAppear:(BOOL)animated {
if(self.traitCollection.horizontalSizeClass != UIUserInterfaceSizeClassCompact){
UISplitViewController *splitViewController = (UISplitViewController *)self.navigationController.parentViewController;
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic;
}
}
This will work , but the masterViewController will "Jump out" which has a very bad visual effect.
Hope can get any help , thank you
UISplitViewController is a complex view controller which consists of two child view controllers. So when you use some segue which is added to any of the child view controller you ask child view controller to perform the segue. And this child view controller has partial control of active window.
In your case you need to ask the split view controller to perform the segue. So you should add the segue to your split view controller which handles active window. This way you will have the fullscreen option.
UPDATE
If you dont wanna using present as modal and want to avoid "Jump out" effect you can hide master using animation
UISplitViewController *splitViewController = [self splitViewController];
[UIView animateWithDuration:0.25 animations:^{
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
} completion:^(BOOL finished) {
[splitViewController showDetailViewController:vc sender:nil];
}];

How do I present a UIViewController modally when a button on it's parent view controller is tapped?

I'm having a little issue with an app I've completed. The problem is with a search view controller presented modally.
I have a search button that when tapped presents the SearchViewController modally.
I have 3 different controllers it can be presented from.
MainViewController > CollectionViewController > DetailViewController
This is actually how the controllers are in the hierarchy.
The results are always displayed on the collection view controller. Basically the collection view is refreshed and the remaining cells show are the result of the search.
Searching from collection view controller:
In the collection view controller, when the search is tapped. The search view controller is presented modally. Search text is entered and a list of matches is shown. When a row is tapped then the search view controller is dismissed and notifies the collection view controller using delegation the collection view is them refreshed with the results.
Searching from detail view controller:
In the detail view controller, when the search is tapped. The detail view controller is popped off the stack revealing the collection view controller. I use delegation to notify the collection view controller that the detail view controller was popped of the stack after the tap of a search button. Immediately the search view controller is opened making it possible to search as if we originally presented the search view controller from the collection view controller.
My issue arises when trying to search from my main view controller. Right now things are working but it doesn't have a very professional feel to it. Let me explain.
To get search working from my main view controller I use delegation. So in the method connected to the search button I perform this segue:
- (void)searchButtonTapped
{
[self performSegueWithIdentifier:#"garmentsCollectionSegue" sender:nil];
}
The protocol is defined in my interface file:
#class VAGMainTableViewViewController;
#protocol VAGMainTableViewControllerDelegate <NSObject>
- (void)mainTableViewControllerDisappearedwithTitleForObject:(NSString *)titleString;
- (void)searchButtonOnMainTableViewControllerTapped;
#end
#interface VAGMainTableViewController : UITableViewController
#property (nonatomic, weak) id<VAGMainTableViewControllerDelegate> aDelegate;
In my preparation before segue I have this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
[self setADelegate: [segue destinationViewController]];
[[self aDelegate] searchButtonOnMainTableViewControllerTapped];
}
Here I set the delegate and also make a call to the delegate method, making the collection view controller aware of the button tap in my main view controller.
Finally in my collection view controller when the tap is detected a call to the method that presents the search view controller modally is made. Search view controller is presented.
In collection view controller
- (void)searchButtonOnMainTableViewControllerTapped
{
[self searchButtonTapped];
}
- (void)searchButtonTapped
{
VAGSearchViewController *svc = [[self storyboard] instantiateViewControllerWithIdentifier:#"searchPageSB"];
svc.delegate = self;
[self presentViewController:svc animated:NO completion:nil];
}
The search view controller notifies the collection view controller it was dismissed using delegation. This is when the querying and refresh of the collection view controller is done and the result of the search is shown.
- (void)searchViewControllerDismissed:(VAGSearchViewController*)searchViewController withTitleForObject:(NSString *)titleString
{
_searchTitleString = titleString;
[self setObjects:nil];
[self performQuery];
}
Ok so this works but it doesn't look professional because for a split second after the push to the collection view controller from the main view controller the collection view is shown before the search view controller is presented.
The feel I'm aiming for is a snappy one. So I'd prefer if the search view controller would be presented instantly.
Hopefully my detailed post give you an idea of what I'm doing.
There is a much more efficient way to do this. The problem is I can't figure it out.
Would appreciate some help
Thanks for your patience
You can do one thing did not push Collection view controller when search button is tapped.
After pushing modalviewControler if search done then you Call the delegate in MainviewController and Then push collection Viewcontroller with no animation in DelegateMethod. its look what you want

Hiding Master View Controller in SplitView regardless of device orientation

I've found lots of people asking for information on how to have the Master view displayed both in landscape and portrait orientation, but what I am trying to do is to having the right master view hidden regardless of the devices orientation and popping in from the side by using a navbar button.
What would help me enormously would be if someone could tell me where the logic for hiding the master view is located/executed when the device reorients. I've been looking at the template that comes with Xcode, Master/detail view for iOS, and I noticed these two following methods are declared in the AppDelegate.m file but I can't seem to find out where they are being executed from:
//Called when a button should be added to the nav bar for a view that is hidden
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController: (UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
barButtonItem.title = NSLocalizedString(#"Master", #"Master");
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
self.masterPopoverController = popoverController;
}
- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
// Called when the view is shown again in the split view, invalidating the button and popover controller.
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
self.masterPopoverController = nil;
}
All help would be appreciated.
You actually have no control over a UISplitViewController. The master view is always present in landscape view, and there is no possible way of changing this.
However, "Matt Gemmell created an excellent custom splitViewController called 'MGSplitViewController'. It is very easily implemented, heavily commented, and contains a lot of excellent features not found with a normal splitViewController (hide master view on landscape view, change placement of the split in landscape view, allow user to change size of split fluidly during runtime, etc)."
Info and demo: http://mattgemmell.com/2010/08/03/mgsplitviewcontroller-updated/
Straight to the source: https://github.com/mattgemmell/MGSplitViewController/
-=-=-=-=-=-=-=-=-=-=-=-
I've posted this before in a similar (but different) question with the same answer here:
How to hide master view in UiSplitviewcontroller in ipad
-=-=-=-=-=-=-=-=-=-=-=-
UPDATE:
In iOS 5.0 and beyond, they have finally added functionality to hide master view in landscape!
-(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
return YES;
}
Reference:
splitViewController in Ipad that doesnt hide in portrait

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

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];
}

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