I have a second view controller which segues from the previous one. How can I adjust the opacity of my SecondViewController so that I may still see the previous view controller under it. Thanks
To present a view modally and still be able to see the presenting view controller under it. Present your SecondViewController in code like this:
let vc = secondViewController
secondViewController.modalPresentationStyle = UIModalPresentationStyle.OverFullScreen
self.presentViewController(vc, animated: true, completion: nil)
Using this, ensure your secondViewController primary view has an alpha value less than 1.0 so you will be able to see through it. Also, the animated parameter can be true or false, it shouldn't affect the result.
Using the modalPresentationStyle accomplish what you are asking.
Just unclick/click Animates option through Interface Builder based on your requirement,
Related
Following Apple's documentation for adding and editing information Apple guide here I have a Viewcontroller with a tableview. The tableview contains a header with a "Add new" Button. If a table row is selected the detailViewController is pushed onto the stack. The detailViewController is also embedded in a UINavigationController, as in Apple's docs. If "Add new" is pressed, another segue is performed which presents the UINavigationController modally, which in turns shows the detailViewController. This works fine and the animation clearly shows a modally presented ViewController.
The detailViewController contains a Cancel Button in the NavigationBar. If it is pressed the following code is run:
#IBAction func cancel(_ sender: UIBarButtonItem) {
// Depending on style of presentation (modal or push presentation), this view controller needs to be dismissed in two different ways.
var isPresentingInAddActionMode = false
if let presentingVC = self.presentingViewController{
isPresentingInAddActionMode = presentingVC is UINavigationController
}
streekgidsModel.undoManager.endUndoGrouping()
print("undo grouping ended and undone")
streekgidsModel.undoManager.undo()
if isPresentingInAddActionMode {
dismiss(animated: true, completion: nil)
}
else if let owningNavigationController = navigationController{
owningNavigationController.popViewController(animated: true)
}
else {
fatalError("The MealViewController is not inside a navigation controller.")
}
}
The first if-statement checks if the property presentingViewController is present, and if so if it is of type UINavigationController. If so, the viewController is presented modally and should be dismissed. If not it is pushed onto the stack and the owningNavigationController should pop the detailViewController.
Running this code does not work as described by Apple. The check on the presentingViewController shows it is present, but the type check gives back "invalid". This is treated as false. The test on the owningNavigationController succeeds (I think it should fail) and the popViewController is executed. As there was no push, the view controller is not popped or dismissed and is still visible. A second press on Cancel executes the func cancel again, which results in an error as there is no longer a group started in the undo manager.
Baffling thing is that I have the same code in another viewcontroller, with similar UIViewTable and navigation and it works fine.
So to frame the question: why does this not work the way Apple describes it, why does my other view controller work as it is supposed to? Any input is appreciated.
BTW, the fatal error text is straight from the docs so the naming is not relevant and it is never executed.
I would start with checking who is presenter.
According to Apple docs on this:
When you present a view controller modally (either explicitly or implicitly) using the present(_:animated:completion:) method, the view controller that was presented has this property set to the view controller that presented it. If the view controller was not presented modally, but one of its ancestors was, this property contains the view controller that presented the ancestor. If neither the current view controller or any of its ancestors were presented modally, the value in this property is nil.
If the docs are correct then your presenter should be your "Viewcontroller with a tableview" which, I guess, is not UINavigationController. If that is the case then you should understand why your code fails.
It depends on your context of course, but I would just simplify a check this way:
var isPresentingInAddActionMode = self.presentingViewController != nil
... // your other code
if isPresentingInAddActionMode {
dismiss(animated: true, completion: nil)
}
else if let owningNavigationController = navigationController{
owningNavigationController.popViewController(animated: true)
}
If I understood your question and intent correctly then it doesn't matter for you who (which class) presented your detailVC and you care only about how your detailVC was presented - either pushed in navigation view controller or presented modally. I think just by checking presentingViewController property you can get that information.
I have a storyboard set up with a UITabBarController which contains a UINavigationController for each tab. For one of the UINavigationControllers there are no transition animations when pushing or presenting a view controller.
There are, at least, two different cases when this happens
1. I have a storyboard segue set up to push the child view controller. The segue triggers when selecting a cell in a table view. The "Animates"-box is checked.
Attempting to programatically push the child view controller yields the same result.
self.navigationController?.pushViewController(nextController, animated: true)
2. There is also no animation when attempting to modally present another view controller from the root view controller of the navigation controller.
modalViewController.modalTransitionStyle = UIModalTransitionStyle.flipHorizontal
self.present(modalViewController, animated: true, completion: nil)
If I present the modalViewController from another view controller the transition is animated which leads me to believe that there is something wrong in the root view controller that is presenting.
Is there a way to disable animations on a UIViewController that I might accidentally have triggered? I have checked and verified that there are no UIView.setAnimationsEnabled(false)
Use self.navigationController?.pushViewController( instead of self.present(
You set up animation in UINavigationController. But you called the function self.present( which is provided by UIViewController. UIViewController of course cannot provide the animation.
In my overridden viewWillDisappear(_ animated: Bool) of the parent view controller I had some code that reset the state of a custom view. The reset did in turn disable actions via CATransaction.setDisableActions(true), thus disabling the transition animations.
Moving the reset to viewDidDisappear(_ animated: Bool) resolved the issue.
let dialog: FriendCheckInDialogViewController = storyboard?.instantiateViewControllerWithIdentifier("FriendCheckInDialogViewController") as! FriendCheckInDialogViewController
dialog.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
If I use
self.navigationController?.presentViewController(dialog, animated: false, completion: nil)
Then transparency works. But popToRootViewControllerAnimated does not, so I cannot go back.
If I use
self.navigationController?.pushViewController(dialog, animated: false)
Then background becomes black instead of transparent. But popToRootViewControllerAnimated works, so I can go back.
What should I do?
You seem to be mixing different presentation styles.
If you present a view controller modally using presentViewController, then you can dismiss it using dismissViewController. In this case you can present the view controller modally over the current view controller.
If you push a view controller onto the navigation controller stack, then you can pop that view controller back off, but the pushed view controller replaces the current view controller, so you can't expose it "underneath".
I searched for similar problems, but none solved my problem. I need to call a new view controller , but when I do it a black screen appears , as I do to associate with the main storyboard screen?
Here is my suggestion:
let vc = storyboard!.instantiateViewControllerWithIdentifier("viewIdentifier") as! viewNeedToCall
You can init and use vc with navigation.
A black screen appears when the simulator can't figure what to present. It seems lost in the sense which controller it has to present.
If it is the first screen then make sure that you have set the initial view controller in Main.storyboard. If not, then you have to call(instantiate) that view controller using the instantiateViewControllerWithIdentifier property of a storyboard.
For e.g.If you want to present a ViewController named as YourViewController then
Make an object of YourViewController, say yourVCObject.
let yourVCObject = self.storyboard?.instantiateViewControllerWithIdentifier("YourViewController") as? YourViewController
Present your desired ViewController with -
self.presentViewController(yourVCObj!, animated: true, completion: nil)
Here connect your class YourViewController in the Identity Inspector in the "Class" and type "YourViewController" in the Storyboard ID and check the "Use Storyboard ID"
Looks like you forgot to connect your VCs to a NAVIGATION CONTROLLER.
Without Navigation controller you cannot move to another VC.
I am new to Swift and have been struggling with this for a while.
I am trying to redirect users based on login status to either "Login" viewcontroller or "Home" viewcontroller.
"Home" viewcontroller has NavigationBar and TabBar and it shows a table. But, when i use the following code, i see only the table. NavigationBar and TabBar are not shown at all.
var view = self.storyboard?.instantiateViewControllerWithIdentifier("HomeViewController") as UIViewController
self.presentViewController(view, animated: true, completion: nil)
Here is my storyboard : https://www.dropbox.com/s/dkcz45n8000gua6/storyboard.png?dl=0
Any help would be appreciated!
Edit (used TabBarController):
var view = self.storyboard?.instantiateViewControllerWithIdentifier("MainTabController") as UITabBarController
self.presentViewController(view, animated: true, completion: nil)
Your problem has nothing to do with being new to swift; it has to do with not understanding storyboards. If you instantiate HomeViewController, and present it, then that's all you will get. The fact that it's embedded in a tab bar controller and navigation controller in the storyboard is not "known" to this bare controller you just instantiated. You should instantiate the tab bar controller instead, and present it. It will take care of instantiating any of its children, and the navigation controller will take care of instantiating its root view controller.