VC1 = Table View
VC2 = New VC
So I'm using A segue to show VC2 from VC1. When using the segue, VC2 shows coming from the bottom of the screen and covering up VC1. When I go back from VC2 to VC1, VC1 does the same animation.
What I was wondering is, is there any way to reverse the back segue from VC2 to VC1 so either VC2 looks as though it is going downwards or VC1 is coming over it from the top of the screen.
Thanks,
Riley
This push effect animation does present modally segue with destination ViewController's transition style Cover Vertical
So when you want to go back from VC 2 to VC 1 with animation opposite to push effect, you can do it just by dismissing VC 2. You don't have to use any segue, just dismiss ViewController.
So from VC 1 you can go to VC 2 by performing segue (you've already done that)
performSegue(withIdentifier: "identifier", sender: self)
and then from VC 2 you can go back to VC 1 by dismissing VC 2
dismiss(animated: true, completion: nil)
Related
Let's say that on my regular flow I have
VC1 -> VC2 -> VC3 -> VC4
But I have a requirement that when I touch a special button on VC1 it needs to go to VC4.
No problem there. The problem is that when I tap the back button on VC4, it needs to go back to VC3 instead of VC1.
I already tried pushing From VC1 -> VC2 and VC2 -> VC3 without animation and then VC3 -> VC4 with animation, but you can see a quick glimpse of VC3 which looks awful.
Any ideas?
I think in this specific case, you can insert a view controller on the navigation controllers stack after presenting the 4th viewController
if let navigationController = navigationController {
navigationController.pushViewController(vc4, animated: true)
let vc3Index = navigationController.viewControllers.count - 1
navigationController.viewControllers.insert(vc3, atIndex: vc3Index)
}
This should place VC3 next in line when the user presses back from VC4. Untested code, btw.
You can modify the UINavCon's viewControllers to achieve the order you want.
func specialButtonInVc1() {
self.navigationController?.pushViewController(fourth, animated: true)
self.navigationController?.viewControllers = [self, second, third,fourth]
}
When I go from VC1 to VC2, if VC2 gets dismissed, I could easily pass data back to VC1 by setting protocal in VC2 and have VC1 conform to it. I want to do something similar, however, with the following difference
When I go from VC1-> NavVC->VC2-> VC3. When VC3 gets dismissed, VC1 is shown. I want to be able to pass data back to VC1 and initiate some function in VC1. For example, I have an image to upload in VC3. As soon as VC3 gets dismissed, I am hoping to have a function in VC1 such as the following function where the image was the data from VC3
func uploadInitiate(image: UIImage) {}
Relationship of the three VC
VC1 is normal VC. It presents VC2 via
let navController = UINavigationController.init(rootViewController: VC2)
self.navigationController?.presentViewController(navController, animated: true, completion: nil)
VC2 is a custom FusumaCamera photo picker from cocoapods.
Once image is selected, I go to VC3 with the selected Image via
self.navigationController!.pushViewController(postVC, animated: true)
At VC3, I allow the user to interact with the image and make comments and press a button to upload to the server. I thought it would be nice to dismiss the VC straight away after button press and allow VC1 to initiate the upload with the data the came from VC3 (That way I can have a progress bar under navigation bar or display any warnings there)
You have multiple patterns that you can apply in similar situations. i will go with the delegation (recomended) example. Imagine you have VC1->
that presents modally a UINavigationController as a root controller and from there VC2 pushes VC3 to the stack. You have to define multiple protocols that will be called on the way you dismiss the VC3
protocol DismissVCDelegate : class {
func dismissViewAndStartUpload(shouldUpload: Bool)
}
Then store the property:
weak var delegate: DismissVCDelegate!
Set the delegate when to the VC3 when you push it from VC2 and conform the the protocol you defined in VC2.
Apply the same pattern all the way back to VC1 where you have passed multiple times the protocol back and you can start you upload task and you should dismiss the modally presented navigation controller like that:
func dismissViewAndStartUpload(shouldUpload: Bool) {
self.presentedViewController.dismissViewControllerAnimated(true, completion: nil)}
I'm facing an issue that I will describe and have found some similar questions, but I don't believe pertains to my issue.
I have a UITabBarController with 2 tabs for VC1 and VC2. VC1 segues to VC4. VC2 segues to VC3 and VC3 segues to VC4. VC4 contains an MPMoviePlayerViewController instance, as depicted below:
- - - - - -> VC1 \
TAB BAR VC / - - -> VC4
\ /
-> VC2 -> VC3 -> /
I have a Notification that listens to when the Video finishes, and dismiss VC4, and go back to whichever parent VC presented VC4, i.e. if VC1 presented VC4, then upon dismissal of VC4, should go back to VC1. Likewise, if VC3 presented VC4, then upon dismissal of VC4, should go back to VC3.
In VC4:
override func viewDidLoad()
{
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "moviePlayerPlayBackDidFinish:",
name: MPMoviePlayerPlaybackDidFinishNotification,
object: player?.moviePlayer)
}
func moviePlayerPlayBackDidFinish(notification: NSNotification)
{
NSNotificationCenter.defaultCenter().removeObserver(
self,
name: MPMoviePlayerPlaybackDidFinishNotification,
object: notification.object
)
player!.view.removeFromSuperview()
self.presentedViewController?.dismissViewControllerAnimated(true, completion: nil)
}
I don't think I'm using the code properly because self.presentedViewController?.dismissViewControllerAnimated(true, completion: nil) stays at VC4.
I found some similar questions:
How to dismiss the current ViewController and go to another View in Swift
How to dismiss VIewController iOS Swift
modal View controllers - how to display and dismiss
However, the sequence segues are different, therefore I can't follow the suggestions.
How can I achieve this? Thanks
UPDATE:
The following code in moviePlayerPlayBackDidFinish properly dismisses VC4 and back to parent VC1 if going from VC1 -> VC4:
self.dismissViewControllerAnimated(true, completion: nil);
However, VC4 does not dismiss when going from VC3 -> VC4.
Finally solved my issue by adding the additional code in moviePlayerPlayBackDidFinish:
self.navigationController?.popViewControllerAnimated(true)
After much research, I found the solution from here: dismissViewControllerAnimated() does not dismiss view controller
I'm using segue navigation with self.perfomSegueWithIndentifier function with type of show segues.I noticed after every navigation other view/viewcontroller did not remove from RAM.What I have to do to solve this
This is what you are looking for:
On Button Tap on View Controller 1:
self.navigationController.pushViewController(secondViewController, animated: true)
On Button Tap on View Controller 2:
self.navigationController?.popViewControllerAnimated(true)
Programmatically
Lets say you have VC1 embed in UINavigationController for now VC1 becomes the top view controller on the navigation stack.
So if you are going VC1 -> VC2
self.navigationController?.pushViewController(vc2, animated: true)
In that case VC2 becomes the top view controller on the navigation stack.
and while coming back from VC2 -> VC1 (Button tap on VC2 perform this statement)
self.navigationController?.popViewControllerAnimated(true)
In that case again VC1 becomes the top view controller on the navigation stack.
Using Segue
Just use Show(e.g Push) and set the identifier for that like i have pushView
and invoke
self.performSegueWithIdentifier("pushView", sender: nil) for moving VC1 -> VC2
and for coming back to VC2 -> VC1
use the same self.navigationController?.popViewControllerAnimated(true)
I have a view controller VC1 that is presented modally over full screen from some other VC0. In my storyboard I have a modal segue from VC1 to VC2 also presenting over full screen. When in my app I can plainly see VC2 over VC1 over VC0, because some parts of their views are transparent. Perfect.
However, I'm going to reuse VC2 many times so I don't want to have a segue to it for each controller in my storyboard, so I want to accomplish this same thing programmatically. However, when I call presentViewController:animated:completion in VC1 to present VC2, the view of VC1 disappears when the modal transition is complete. When VC2 is dismissed, the view of VC1 reappears when the transition animation is complete.
How can I get the same effect programmatically as when I'm using the storyboard segue?
let newView = self.storyboard!.instantiateViewControllerWithIdentifier("NewViewController") as! NewViewController
newView.modalPresentationStyle = UIModalPresentationStyle.OverFullScreen
self.presentViewController(newView, animated: true, completion: nil)
You can only present on a visible controller, which is usually the rootViewController. But when there is a modally-presented controller, it covers the root controller, so you can't use that. But you can present on the modal, which is accessed though rootViewController.prsentedViewController. Here's some code:
let rootVC = window?.rootViewController
let presentingVC = (rootVC?.presentedViewController ?? rootVC)
presentingVC?.present(myController, animated: true, completion: nil)
You don't need to change the modalPresentationStyle.
You need to set the modalPresentationStyle property of the presented controller to UIModalPresentationOverFullScreen. Set that property just before you call presentViewController:animated:completion.