Display Modal ViewController in PageViewController - ios

I have a master page in my application that is based on PageViewController. On that master page I have a side bar that provides options to the user. One of the options is to display "About" information regarding the application. When the user click the About button in the side bar, I want to display my AboutViewController as modal. It appears all my linking up is correct however when I click the About menu option in the side bar, the whole screen simply goes black (which is the background color or my AboutViewController) and none of the content in my AboutViewController is visible.
Here is the code for my PageViewController. The highlighted code is the code that displays the modal view controller.
Here is a screen show of About View Controller Scene that I am trying to display.
Where is a screen shot of what the app looks like before I click the About button:
This is how a click the About button:
This is what I get after I click the about button:
Any suggestions as to what I am doing wrong?
UPDATE: Per the comment provided I updated my code as follows and I am still having the same problem.
gobj_sideBar.showSideBar(false)
iobj_AboutViewController = AboutViewController()
iobj_AboutViewController?.iobj_CloseAboutInfoDelegate = self
iobj_AboutViewController!.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
// Cover Vertical is necessary for CurrentContext
iobj_AboutViewController!.modalPresentationStyle = .CurrentContext
// Display on top of current UIView
self.presentViewController(iobj_AboutViewController!, animated: true, completion: nil)
Also - I don;t believe a blank page is being displayed as in the code for my About View Controller I do have the following line of code which turns off the status bar and the status bar is not visible on the scene displayed when I click the about button.
override func prefersStatusBarHidden() -> Bool {
return true;
}
OK So I switched to using Modal Segues as suggest and that mostly works. The only challenge I have now is that I want the About View Controller to display as a small popup type view but instead it is taking up the full screen as seen below:
These are the properties I have set for my About view controller. Any idea how I should change it so the view comes up as a popup type window where the background is grayed out but the About view does not take up the entire screen?

I am not experienced enough to tell what's wrong but I am spotting some mistakes in your code :
modalTransitionStyle and modalPresentationStyle are to be set on the presented view controller not on the presenting.
You instantiate an AboutViewController, save a reference to it and set self as its delegate but in the call to presentViewController(...) you instantiate another AboutViewController
Also consider that the black is not the background color of your About scene but instead the color of a blank screen.
If I were you, I'd use a segue for that about scene as well, it's less error prone. And instead of delegation to dismiss the About view controller, try an unwind segue.

Related

What is the standard method for implementing navigation menus in swift?

I'm trying to create navigation through the use of a menu in my app, but I'm not sure how it should be done. I currently have a system set out like this:
ContainerViewController
|
+---CenterNavigationController
|
+---ViewControllerA [i.e. the root view controller which will be changed]
|
+---MenuViewController [pushed to navigation stack on btn press]
and when a item in the menu is pressed to load another view controller, MenuViewController calls a delegate method in the ContainerViewController which replaces the NavigationController with a new one with a different root
let newVC = ViewControllerB()
CenterNavigationController = UINavigationController(rootViewController: newVC)
However this looks janky, both in the code and in the aesthetics of the app.
I'm not sure how to do this properly. I'm wanting the menu to be overlayed onto the current view, and have the ability to click 'back' in the menu to go back to what was showing on screen before the menuVC was loaded. How can I do this?
You do all correct. If navigation animation isn't good, then improve it. You can show menu animated from the left side and reload CenterNavigationController without animation. As for transparence, then just change the color of the main view of the menu view controller to semitransparent. The first subview that contains all menu items should be non-transparent and have lower width and sticked to the left side. That's it.
I think you should not push menu view controller into the navigation stack. Just load it right into the UINavigationView controller.
You can check loadViewController (line 251) method here https://gitlab.com/seriyvolk83/SwiftEx/blob/master/Source/UIExtensions.swift
It loads view controller into another view controller in a given bounds. To remove it later (close menu) you can use remove() (see line 321)
Hamburger menu is antipattern on iOS, I suggest using UITabBarController. If someone is holding a gun to your head and forcing you to put a hamburger menu in your app then use something like this: https://github.com/jonkykong/SideMenu

Bar item button not displayed at runtime but visible at design time in a modal view

I have being trying different things and looking around for a while without finding an answer to my problem. Maybe I'm doing something fundamentally wrong.
The sample application consists of:
A first view controller that displays a second view controller using a segue. This works fine.
A second view controller, in which I have simulated the display of a third view programmatically, which contains a bar item button (named "Done") that I would like to display.
The bar item button in the third view controller is not displayed at runtime but is displayed in IntefaceBuidler at design time.
This third view controller needs to be displayed modal.
What I'm doing wrong to display this bar item button?
A sample project illustrating the problem is available here.
Below a screen capture of the bar item button at design time:
Below a screen capture of the bar item button not showing at design time:
PS:
Please disregard the "Unknown class ThirdViewControlller in Interface Builder file.", since the ThirdViewController is displayed fine at runtime. Also, the "Done" button in the middle of the view works fine.
In SecondViewController you need to push the third onto the navigation controller stack like so:
self.navigationController?.pushViewController(thirdViewController, animated: true)
You are currently presenting it as a modal. Also, you've unnecessarily added a second UINavigationController to your storyboard (for the third view controller)
If you want to present a modal, then you'd need to embed the controller in a navigation controller:
let navController = UINavigationController(rootViewController: thirdViewController)
self.present(navController, animated: false)
If you prefer to keep this within the storyboard, then you need to provide a identifier for the UINavigationController and insatiate that in your function.
The above button is a navigation bar item that will only be displayed on the navigation bar . For achieving your desired result , you first have to embed the navigation controller at least in your second viewcontroller and then you should do a push segue rather than modal . Navigation controller can be added by
whith your second viewcontroller selected go to Editor\Embed In\Navigation Controller
for pushing the viewcontroller programatically onto user navigation controller's stack use
self.navigationController?.pushViewController(nextViewController, animated: true)

Transition from UIViewController to TabBarViewController

I have been searching for a solution for 6 hours, and come up with nothing that applies to my situation. my storyboard follows the flow of:
TabBarViewController -> NavigationController ->TableViewController -> UIViewController (see picture below)
When the "Notify" button, in the last view controller (Stranger view controller), is clicked, I want to programmatically transition/segue from that View Controller(Stranger View Controller), to a different child of the TabBarViewController (it is the controller titled "Look Around" within the illustration).
Every time I perform a traditional segue:
option + drag segue from Stranger View Controller --> Look Around
View controller
Give segue an identifier
programmatically use self.performSegueWithIdentifier.
I get a transition. but the "Look Around" tab bar is gone in the storyboard, and in the simulator, once I hit "Notify", the view changes to the "look around" view, but the tab bar below does not reflect that change, as it still has the previous tab highlighted.
I have already handled all the other processing within the IBAction function that I need to handle. It is just a matter of, correctly, sending the user to a different view, once they have hit "Notify".
Any guidance on this would be greatly appreciated.
If you have any questions or concerns for me, please do not hesitate to ask. I am new at this, and am open to any help.
ViewController is a child of NavigationBar and NavigationBarController is a Child of TabBarController. So Segue is not required as it will disturb the flow.
Try programmatically
#IBAction func notifyButtonTapped(sender: AnyObject) {
tabBarController?.selectedIndex = 1
tabBarController?.tabBar.hidden = false
self.navigationController?.popToRootViewControllerAnimated(false)
}

Showing a view controller in Modal Dialog programmatically is appearing as full screen

I have 2 swift View controllers and i want the second one to show as a modal dialog ( like bootstrap modal in web) on top of the first view when i click a button. I used the below code to achieve this, but the second view controller is still appearing full screen!
This is the code i execute to show the second view controller
var addCtrl = self.storyboard?.instantiateViewControllerWithIdentifier("mCtrl")
as? ModalContentViewController
addCtrl!.modalPresentationStyle = .Popover
presentViewController(addCtrl!, animated: true, completion: nil)
mCtrl is the storyboard id of the second viewcontroller.
What am i missing here ? My objective is to show the second view controller in a modal dialog.
EDIT : I am trying to make it work on iPhone.
You don't mention whether you're on iPhone or iPad. Assuming you're on iPad, if you want something like a modal dialog, then you'd be better off using UIModalPresentationFormSheet, which in swift I guess would be .FormSheet. If you really want to use a popover, you'll need to tell it where to popover from. You'd do this by setting the sourceView and sourceRect, or the barButtonItem properties of the controller's popoverPresentationController, after the call to presentViewController.
If you're on the iPhone, you'd still get a full screen presentation in both these cases. However, you can get the iPad style presentations if you set the presenting controller to be the presented controller's presentationController's delegate, before the call to presentViewController, and then implement adaptivePresentationStyleForPresentationController:traitCollection to always return UIModalPresentationNone.
Based on Apple's documentation, you try setting preferredContentSize explicitly for the popover view. Something like
addCtrl!.preferredContentSize = CGSizeMake(200, 100)
The value in this property is used primarily when displaying the view controller’s content in a popover but may also be used in other situations. Changing the value of this property while the view controller is being displayed in a popover animates the size change; however, the change is not animated if you specify a width or height of 0.0.

Swap/ Transitioning between views iOS programming

I am a newbie to IOS programming and currently i have a tab bar application with two tabs. I have two questions.
The first tab shows a map, imagine it with some pushpins. There is a button on the navigation bar and when this is clicked i want the map view to to move out and a list view to come in. You can see the UI from the image. The button is called list.
Now when i click list I want this view to go away and the list view to come in. So here are my questions ?
1) How do i do this ? I tried the navigation model but i don't want that because I do not want a back button. I tried to make two different views and just dragged the button to that view but the app crashes. I just want the list button on the nab bar and when clicked the view changes to the list view and the button text changes to map. So now if I click the button again it should go back to the map view and the button changes to list.
2) How do i achieve the animations for this ? Ive seen some app where the page flips around and I've seen some options like reducing the opacity etc but I want to achieve the flip animation.
Thank You for any help I get. I really appreciate it.
Interface Builder can do most of this. Hold down the control key and drag from your map View Controller's UIBarButtonItem titled "List" to your list View Controller, then choose the Action Segue "modal". An arrow appears representing the segue; click on it and use the Attributes Inspector to change the Transition to "Flip Horizontal". Here's a video
Or, you could do this programmatically with presentViewController:animated:completion.
Now to get back to the map from the list, I believe that must be done programatically. Create a method that calls dismissViewControllerAnimated:completion: and make your list View Controller's UIBarButtonItem titled "Map" trigger it.
After reading your comments, I am wondering... if the structure of your app is logically a tabbed app structure (as indeed you refer to it as a 'tab bar application'), shouldn't you consider using the UITabViewController instead of a NavigationController? That is what it is designed to do, after all.
If you do use a TabViewController you should reconsider your desire for flip animation, as that doesn't really make UI-sense for tabs. If you can dispense with the flip animation, TabViewController could be a good way to go and you should at least experiment with that before dismissing the idea. It is also designed to grow... you can incorporate any number of tabs in a tab bar. Check out the apple docs (with pictures!)
You will notice that tabs are at the foot of the screen, whereas your 'tab' navController buttons are in a navbar at the top of the screen. This also helps as your app grows, as it is straightforward - from a UI design point of view and programmatically - to incorporate navControllers as navigation tools within individual tabs. For example, if your map/list flip routine does indeed make sense for this part of you app, you can keep this as a single tab (in it's own navigationController) and add other tabs for other parts of the app...
update
From your comment, you are saying that you are interested in the navController-inside-tabBarController setup. In this case here are some ways to get flip transitions AND no back button..
(1) modal presentation
The easiest way to get what you want is to set up one of your viewControllers (say the map view) to present the other one (the list view) modally.
If in the storyboard:
embed your mapViewController in a navController with a navbar button for navigation to the listView as in your picture
add your listViewController to the storyboard and embed it in it's own navContoller (not the mapViewController's navController). Drag a barButtonItem to this navController and wire it up to an IBAction in listViewController
CTRL-drag from mapViewController's 'list' button to the listViewController to create a segue. Select the segue and in the attributes inspector set the segue type to 'modal', with transition 'flips horizontal' and 'animated' checked. Give it a name in case you want to refer to it in code.
in the listViewController's IBAction add this:
[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
That should achieve your result. You can use the completion block to send information back from the list view to the map view, and/or set the map view as the listView's delegate.
If you are not using the storyboard check this apple guide
Presenting View Controllers from Other View Controllers
especially "Presenting a View Controller and Choosing a Transition Style".
There is one catch with this approach - when the presented view flips onto the screen, the entire previous view, including the tab bar, is flipped out of the way. The idea is that this is a modal view which the user is required to dismiss before doing anything else in the app.
(2) push/pop in a single navController If this does not suit your intent, you can navigate using a single NavigationController with push and popping of views, and you can hide the back button ... but you really would need to keep the back button functionality as you do want to go back to the mapView, not on to a new map view.
To hide the back button try:
self.navigationItem.hidesBackButton = YES
in the uppermost viewControllers' viewDidLoad
Then you can add a barButtonItem in the xib/storyboard, with this kind of IBAction:
[self popViewControllerAnimated:NO]
or
[self popToRootViewControllerAnimated:NO]
You would have to construct the flip animation in code as it is not supported as a built-in with UINavigationController (best left as an exercise for the reader!)
(3) swapping views in a single viewController As ghettopia has suggested, you could use a single viewController inside a navController (or with a manually place navBar) and swap two views around using the UIView class methods
transitionFromView:toView:duration:options:animations:completion
transitionWithView:duration:options:animations:completion.
This could be a good simplifying solution as your list and map are essentially two views of the same data model.

Resources