I have created Master detail application with multiple detail view controllers connected to a split view via replace segue. On landscape orientation everything works fine, but on portrait orientation I am missing button to open masters table view and swipe on left side of the screen is not working and not opening master side of the app.
EDIT:
In my DetailViewController I have two methods, same as in template provided by xcode for master-detail app:
#pragma mark - Split view
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
barButtonItem.title = NSLocalizedString(#"MasterButton", #"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;
}
EDIT 2:
On change of my detailViewController, I change delegate too.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *destinationViewController = [segue destinationViewController];
if ([destinationViewController conformsToProtocol:#protocol(UISplitViewControllerDelegate)]) {
self.splitViewController.delegate = (id)destinationViewController;
}
else {
self.splitViewController.delegate = nil;
}
}
EDIT 3:
I finally resolved my issue by adding this line of code in every DetailViewController that I created:
self.splitViewController.delegate = self;
You need place barButtonItem from
- (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc
at detail view controller's navigationBar.
1) This is for the bar button:
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
self.popoverController = popoverController;
barButtonItem.title = NSLocalizedString(#"List", #"List");
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
self.masterPopoverController = popoverController;
}
2) and if you want to add UIButton then try below:
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
self.popoverController = popoverController;
UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom];
[btn setImage:[UIImage imageNamed:#"list.png"] forState:UIControlStateNormal];
//[btn setImage:[UIImage imageNamed:#"list.png"] forState:UIControlStateHighlighted];
[btn setFrame:CGRectMake(0, 0, 50, 30)];
[btn addTarget:barButtonItem.target action:barButtonItem.action forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem=[[UIBarButtonItem alloc]initWithCustomView:btn];
self.masterPopoverController = popoverController;
}
Related
I use a UIPageViewController for two view controllers. In the first view controller I have a 'NEXT' button to go to the second view controller. My question is: How can I wire it up?
In my first and second view controllers I do not have code yet. However, in my RootViewController I have this code:
- (void)viewDidLoad {
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PageViewController2"];
self.pageViewController.dataSource = self;
SeekerRegistrasiViewController *tvc = [self.storyboard instantiateViewControllerWithIdentifier:#"seeker1"];
Seeker2RegistrasiViewController *pvc;
self.array =[NSArray arrayWithObjects:tvc, pvc, nil];
[self.pageViewController setViewControllers:self.array direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height -60);
self.pageViewController.view.backgroundColor = [UIColor clearColor];
[self addChildViewController:pageViewController];
[self.view addSubview:pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{
if ([viewController isKindOfClass:[Seeker2RegistrasiViewController class]]) {
SeekerRegistrasiViewController *pvc = [self.storyboard instantiateViewControllerWithIdentifier:#"seeker1"];
return pvc;
}
else return nil;
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{
if ([viewController isKindOfClass:[SeekerRegistrasiViewController class]]) {
Seeker2RegistrasiViewController *tvc = [self.storyboard instantiateViewControllerWithIdentifier:#"seeker2"];
return tvc;
}
else return nil;
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
return 2;
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
return 0;
}
I would appreciate any help that would guide me in the right direction.
You can do it using setViewControllers:direction:animated:completion:.
Look at this answer: Is it possible to Turn page programmatically in UIPageViewController?
You basically set again all the view controllers (already switched), define a direction (which the animation will use, for example, UIPageViewControllerNavigationDirectionForward), use YES for animated and a completion block for processing afterwards (like updating the currentPage index you manage).
In my iPad App I'm using a UISplitViewController with two UINavigationControllers as master and detail. In Potrait I'd like the master to be hidden and accessible via UIPopoverViewController. This is the implementation of my UISplitViewController subclass, which works fine:
- (id)init {
self = [super init];
if (self) {
_splitViewController = [[UISplitViewController alloc] init];
_splitViewController.delegate = self;
_searchViewController = [[UIViewController alloc] init];
_searchViewController.view.backgroundColor = [UIColor whiteColor];
_masterNavController = [[UINavigationController alloc] initWithRootViewController:_searchViewController];
_masterNavController.navigationBar.translucent = NO;
_mapViewController = [[MapViewController_iPad alloc] init];
_detailNavController = [[UINavigationController alloc] initWithRootViewController:_mapViewController];
_detailNavController.navigationBar.translucent = NO;
_splitViewController.viewControllers = #[_masterNavController, _detailNavController];
_splitViewController.view.backgroundColor = [UIColor redColor];
}
return self;
}
#pragma mark -
#pragma mark - UISplitViewControllerDelegate
- (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc {
svc.view.backgroundColor = [UIColor redColor];
barButtonItem.title = NSLocalizedString(#"ipad_search_vc_bar_button_title", #"Name of the master view controller button on iPad");
[self.mapViewController.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
}
- (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
svc.view.backgroundColor = [UIColor redColor];
[self.mapViewController.navigationItem setLeftBarButtonItem:nil animated:YES];
}
- (void)splitViewController:(UISplitViewController *)svc popoverController:(UIPopoverController *)pc willPresentViewController:(UIViewController *)aViewController {
svc.view.backgroundColor = [UIColor redColor];
[pc setPopoverBackgroundViewClass:[CustomPopoverBackgroundView class]];
}
This is how it looks:
After starting the App the first time and tapping the UIBarButton, the master looks like the following:
After hiding and tapping the UIBarButton item the second time, the master looks like it's supposed to. It has the red divider line instead of the standard colored one:
Now, the CustomBackgroundView that is used in the UISplitViewController delegate is actually being instantiated, but somehow not used the first time around.
Any idea how I could force the UIPopOverController to use the CustomBackgroundView the first time?
I ended up simply adding a subview to the UISplitViewController's view, which has the same color as the UINavigationBar.
UISplitViewController *splitViewController = [[UISplitViewController alloc] init];
[splitViewController.view addSubview:coloredView];
Is your Split View your root view controller? It looks like you have your split view within a Navigation Controller, which is not allowed. That would explain your graphical bugs.
I am trying to add a button to my navigation bar on my detail view to show the master view when in portrait mode but the button isn't showing up. Can anyone help or offer suggestions?
Here is how I was trying to do it in the detail view:
- (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc
{
mainMenu = barButtonItem;
[mainMenu setTitle:#"Menu"];
[[self navigationItem]setLeftBarButtonItem:mainMenu];
}
- (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
if (mainMenu == [[self navigationItem]leftBarButtonItem])
{
[[self navigationItem]setLeftBarButtonItem:nil];
}
}
Here is how I'm loading the detail view when selecting a row in my master view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *details = [self.splitViewController.viewControllers mutableCopy];
UINavigationController *detailNav = [[UINavigationController alloc]initWithRootViewController:webViewController];
[details replaceObjectAtIndex:1 withObject:detailNav];
self.splitViewController.viewControllers = details;
KFBAppDelegate *appDelegate = (KFBAppDelegate *)[[UIApplication sharedApplication]delegate];
appDelegate.window.rootViewController = self.splitViewController;
I've added this to viewDidLoad and the button shows up now but I'm not sure how to get it to show the master view.
mainMenu = [[UIBarButtonItem alloc]init];
[mainMenu setTitle:#"Menu"];
self.navigationItem.leftBarButtonItem = mainMenu;
Here is a picture of what it looks like when I swipe from the left to show the master view.
I've managed to get a left button to appear but now I don't know how to have it open the master view. Here is how I got the button to show up:
mainMenu = [[UIBarButtonItem alloc]init];
[mainMenu setTitle:#"Menu"];
self.navigationItem.leftBarButtonItem = mainMenu;
Rather than left button, use right bar button and it will show. The problem is the button on the left gets hidden by the default button of the vavigation controller. Try the right bar button.
Edit
This is a generic method that is placed in view did load to include a right bar button. then you can access is in other methods. hope it helps.
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
In here insert new object in the selector is the IBAction that you use to declare what that button has to do.
I have a searchcontrollerviewcontroller, detailviewcontroller and a filterviewcontroller
In Appdelegate I added the first 2 as splitview controller and delegate to detailviewcontroller like this:
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:searchViewController, detailNavigationController, nil];
when the ipad turns it shows buttons for the popoverview
- (void)splitViewController:(UISplitViewController *)splitController
willHideViewController:(UIViewController *)viewController
withBarButtonItem:(UIBarButtonItem *)barButtonItem
forPopoverController:(UIPopoverController *)popoverController{
UIBarButtonItem *filterbutton = [[UIBarButtonItem alloc]initWithTitle:#"Filter" style:UIBarButtonItemStylePlain target:nil action:#selector(showFilterPopover:)];
barButtonItem.title = NSLocalizedString(#"Search", #"Search results");
[self.navigationItem setLeftBarButtonItems:[NSArray arrayWithObjects:barButtonItem,filterbutton, nil] animated:YES];
self.masterPopoverController = popoverController;
}
I init the filterview in here
-(void)showFilterPopover: (id) sender{
FilterViewController *controller = [[FilterViewController alloc]initWithNibName:#"FilterViewController" bundle:nil];
UIPopoverController *popover =
[[UIPopoverController alloc] initWithContentViewController:controller];
popover.delegate = self;
self.masterPopoverController = popover;
[self.masterPopoverController
presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
But nothing happens, the popover works for the detailview but not for the filterview....
Am I forgetting something ?
I'm trying to hide the master view in UISplitView in the landscape mode. This i want to do on an button click. In my navigation bar I have a button on click of which I want to hide the master view in landscape mode. Also if the master view is hidden then on click of that same button it should show the master view back. All this needs to be done in master view. I referred to the following function
-(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
return YES;
}
But it hides master view on view load in spite of button click. Below is my code for detail view
- (void)setDetailItem:(id)newDetailItem {
if (detailItem != newDetailItem) {
[detailItem release];
detailItem = [newDetailItem retain];
// Update the view.
NSLog(#"Detail item in detail view::%#",detailItem);
NSString *imageName = [NSString stringWithFormat:#"%#.jpg",[detailItem description]];
NSLog(#"Image name is::%#",imageName);
self.imageToDisplay.image = [UIImage imageNamed:imageName];
[self configureView];
}
if (mainpopover != nil) {
[mainpopover dismissPopoverAnimated:YES];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
detailDescriptionLabel.text = [detailItem description];
openInButton = [[UIBarButtonItem alloc] initWithTitle:#"OpenIn" style:UIBarButtonItemStyleDone target:self action:#selector(openIn)];
favoritesButton = [[UIBarButtonItem alloc] initWithTitle:#"*" style:UIBarButtonItemStyleDone target:self action:#selector(markFavorite)];
emailButton = [[UIBarButtonItem alloc] initWithTitle:#"E" style:UIBarButtonItemStyleDone target:self action:#selector(emailFile)];
uploadButton = [[UIBarButtonItem alloc] initWithTitle:#"#" style:UIBarButtonItemStyleDone target:self action:#selector(uploadFile)];
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:openInButton, favoritesButton,emailButton, uploadButton, nil];
}
#pragma mark -
#pragma mark Split view support
-(void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc
{
barButtonItem.title = #"Quicksync";
self.navigationItem.leftBarButtonItem = barButtonItem;
self.mainpopover = pc;
}
// Called when the view is shown again in the split view, invalidating the button and popover controller.
-(void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
myBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"<" style:UIBarButtonItemStyleDone target:self action:#selector(hideMasterScreen)];
self.navigationItem.leftBarButtonItem = myBarButtonItem;
self.mainpopover = nil;
}
// Called when the hidden view controller is about to be displayed in a popover.
- (void)splitViewController:(UISplitViewController*)svc popoverController:(UIPopoverController*)pc willPresentViewController:(UIViewController *)aViewController
{
// Check to see if the popover presented from the "Tap" UIBarButtonItem is visible.
if ([barButtonItemPopover isPopoverVisible]) {
// Dismiss the popover.
[barButtonItemPopover dismissPopoverAnimated:YES];
}
}
-(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
return YES;
}