Swipe Right to Dismiss ViewControlelr without using Storyboard Swift - ios

How to dismiss any View Controller without using Storyboard ? and do I have to use UINavigationController to achieve this ? if not how then ?

if someone is still struggling to dissmiss on swipe (left,right,bottom,top)
i came across a very elegant and decent cocapod panslip
with a very simple usage
just call this method in viewDidLoad()
For viewController embedded in navigation Controller
let viewControllerVC = self.navigationController
viewControllerVC!.ps.enable(slipDirection: .leftToRight){
//anything you want to do after dissming
}
For Simple View Controller
let viewControllerVC = self
viewControllerVC!.ps.enable(slipDirection: .leftToRight){
//anything you want to do after dissming
}
For TableView embedded in View Controller
let viewControllerVC = self.YourTableview.parentContainerViewController()
viewControllerVC!.ps.enable(slipDirection: .leftToRight){
//anything you want to do after dissminn
}

The way to dismiss a view controller is to call a dismiss method on the presenting view controller. If you presented your child controller from a parent by calling self.present(_:animated:) then you can call self.dismiss(animated:). If you used a navigationController and called navigationController.push(_:animated:) then you need to tell the navigation controller to dismiss with navigationController.popViewController(animated:)
Method names might not be exact, but you should be able to figure it our with autocomplete.

If you want to swipe right is not a dismiss, but I think that what you want it to embed the UIViewController inside a UINavigationController.
For example:
if let vc = UIStoryboard(name: "YourStoryboard", bundle: nil).instantiateViewController(withIdentifier: "YourViewController") as? YourViewController {
let navigation = UINavigationController(rootViewController: vc)
navigationController?.pushViewController(vc, animated: true)
}

Related

How can I set back to first view controller by navigation controller in code in present without segue?

I have in my project tow view controller and I linked the first VC with navigation controller but the problem is : I used present to go to second VC (that mean I didn't use segue) ... how can I set back to first VC in navigation Controller by code (without segue) .
picture from my storyboard
my code :
let storyboard = self.storyboard
let viewcontroller = storyboard?.instantiateViewController(withIdentifier: "contact_detail") as! ViewController2
viewcontroller.arr2 = arr
present(viewcontroller, animated: true, completion: nil)
With the dismiss method it will work.
Dismisses the view controller that was presented modally by the view controller. (Apple Docs)
self.dismiss(animated: true, completion: nil)
If you are presenting a viewcontroller with present method, you can dismiss it with dismiss method.
If you are adding any view controller with push method then only it will get added to your navigation stack and you can remove it by calling popviewcontroller on it's back action.
Here, you are presenting a viewcontroller, hence it will not get added to your first navigation stack and you can not remove it with pop action on click of back.
If you are looking for a back button like feature on presented view controller, you can add a back button in toolbar, dismiss a viewcontroller on back button action, and can animate it like a popnavigation while dismissing.
extension UINavigationController {
public func removeViewController(classes : [String]) {
var vcs = [UIViewControllers]()
for viewController in self.viewControllers {
let name = viewController.className
if !classes.contains(name) {
vcs.append(viewController)
}
}
if classes.count < vcs.count {
self.viewControllers = vcs
}
}
}
now think you have 4 viewControllers , A, B, C, D, you want to remove B and C and Move Back To A
In D's View Controller
override func viewDidLoad() {
super.viewDidLoad()
//your works
let viewControllersToRemove = [String(describing: type(of:B)), String(describing: type(of:C))]
navigationController.removeViewControoler(classes : viewControllersToRemove)
}
I solved this by using pushViewController
self.navigationController?.pushViewController(MyViewController, animated: true)

Setting back button when presenting a view controller

On clicking a button I display a view controller using the following code:
let navController = UINavigationController(rootViewController: locationVC)
navController.navigationBar.barTintColor = StyleHelper.navBarColor()
navController.navigationBar.tintColor = UIColor.whiteColor()
navController.navigationItem.backBarButtonItem = UIBarButtonItem(image: UIImage(named: "back_arrow"), style: .Plain, target: locationVC, action: nil)
self.presentViewController(navController, animated: true, completion: nil)
But the back button does not appear on the locationVC
What am I doing wrong? Please help
Multiple issues with code.
Issue 1:
You should update viewController's bar button item and not navigationController's bar button item.
So this is wrong
navController.navigationItem.backBarButtonItem
Whats correct
self.navigationItem.backBarButtonItem
Issue 2:
The above code won't work because your current viewController is not pushed by any other VC so it cant show back button. What you need is leftBarButtonItem
So in your VC you can write
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Abcd", style: .done, target: self, action: yourSelectorHere)
}
O/P:
Back button only appears for view controllers in the navigation stack.
you creating new navigation controller stack and making locationVC as root controller so there won't be any view controller to go back.
If you push another view controller to the navigation stack then you will get back button.
In a horizontally regular environment, the view controller is
presented in the style specified by the modalPresentationStyle
property. In a horizontally compact environment, the view controller
is presented full screen by default. doc: presentViewController
So, if you use present a view controller it will not show in navigation controller thus no back button
For this case you need to push view controller.
From storyboard:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier:
"newViewController") as! YourViewController
self.navigationController?.pushViewController(vc, animated: true)
Programmatically
let vc = YourViewController()
self.navigationController?.pushViewController(vc, animated: true)
presenting will present your VC on top of everything and not push it to the navigayionCOntroller.
You should push your VC to the NavigationController instead like so:
var rootViewController = self.window!.rootViewController as UINavigationController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var profileViewController = mainStoryboard.instantiateViewControllerWithIdentifier("profile") as ProfileViewController
rootViewController.pushToViewController(profileViewController, animated: true)
presentViewController is a method that bring a modal view to your navigation, not part of the navigationController.
Instead you should use the pushToViewController method on the navigationController (and not creating a new one) like that :
if let navigationController = self.navigationController {
navigationController.pushViewController(locationVC, animated: true)
}
The presenting view controller is responsible for dismissing the view controller is presented. If you call this method on the presented view controller itself, UIKit asks the presenting view controller to handle the dismissal.
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.
If you want to retain a reference to the view controller's presented view controller, get the value in the presentedViewController property before calling this method.
#IBAction func backButtonAction(_ sender: UIButton) {
self.dismiss(animated: true)
}
More: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621505-dismiss

Log out and clear VCs below current VC

We are looking to change the way a user logs out of our app. In order to do that, we want to dismiss all the VCs below the current VC and put another VC on top as the root VC. Right now we are doing this which I believe does not dismiss any VC below from memory.
let viewController = storyboard?.instantiateViewController(withIdentifier: "SignIn")
if let unwrappedViewController = viewController {
self.present(unwrappedViewController, animated: true, completion: {})
}
The problem is that the VC that we want to put on top is not embedded in a Navigation Controller or tab bar controller. How would we dismiss the VCs and set the new VC as the main VC as if the user was opening the app for the first time without having previously logged in? We also do want the transition to be animated with whatever animation is normal for that event (modal animation is fine). I have read a bunch of different ways on doing it but I want to know which way is best practice and should be implemented specifically dismissing all VCs and putting a new VC that isn't in a Nav controller on top.
If you can access the UIWindow of the app, you can set its rootViewController property to your sign-in view controller, effectively removing all current view controllers and adding the sign-in view controller instead. Here's an example:
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
// Should remove all subsequent view controllers from memory.
appDelegate.window?.rootViewController.dismiss(animated: true, completion: nil)
// Set the root view controller to a new instance of the sign in view controller.
appDelegate.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SignIn")

custom push segue animation

hello I want to have the push segue default animation while Presenting View Controller.
I have three controllers In my storyBoard. FirstController is attached to the navigationController. first controller and second is connected through segue as present Modally. I am launching the third controller from second controller like this
let takeProductPhotoController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("takeProductPhotoController") as! TakeProductPhotoController
let nav = UINavigationController(rootViewController: takeProductPhotoController )
self.presentViewController(nav, animated:true, completion:nil)
The problem is ThirdController is popping up like modally I mean from the bottom which I don't want. I want to have a animation like push segue
I think It will work If I do self.pushViewController but pushViewController is not in this self
You need to do:
self.navigationController?.pushViewController(nav, animated:true)

How to pop view controller to one of the previous view controllers in swift?

I have been trying to pop my view controller to one of previous view controllers in my view stack. Assume that, There are firstVC, secondVC, thirdVC and fourthVC viewcontrollers in my view stack. The current view controller is fourth one, and there is a tableview in fourthVC. If user delete all the rows in tableview, I should direct the user to secondVC. I had an idea that I would create another navigationcontroller and present it with presentViewController command. However, this is not a solution for my problem. Because I thougt that a navigation problem appears for this case. How can I find best solution for this case ?
Thank you for your answers,
Best regards
Instead of doing a generic popViewControllerAnimated: call, use popToViewController:animated:. You could detect if the user has deleted all of the rows in which case, do something like this (otherwise just pop one view controller):
let viewControllers: [UIViewController] = self.navigationController!.viewControllers as [UIViewController];
self.navigationController!.popToViewController(viewControllers[viewControllers.count - 2], animated: true);
If you want to pop to a specific view control and dont know the count to go back you can use this:
let viewControllers: [UIViewController] = self.navigationController!.viewControllers as! [UIViewController];
for aViewController in viewControllers {
if(aViewController is ViewControllerYouWantToGoTo){
self.navigationController!.popToViewController(aViewController, animated: true);
}
}
After lots of effort I have created swift extension of back to a particular view controller in Swift 3.0.
extension UINavigationController {
func backToViewController(viewController: Swift.AnyClass) {
for element in viewControllers as Array {
if element.isKind(of: viewController) {
self.popToViewController(element, animated: true)
break
}
}
}
}
Method calling:
self.navigationController?.backToViewController(viewController: BarCodeScannerVC.self)
Here you can do this by the find the controller from the UINavigationController stack and with the help of for loop and check the condition of your desire controller and if the condition gets fulfilled it will pop to the destionation controller.
let viewControllersStack: [UIViewController] = self.navigationController!.viewControllers
for firstViewcontroller in viewControllersStack
{
if firstViewcontroller is desireViewController
{
self.navigationController!.popToViewController(firstViewcontroller, animated: true)
}
}

Resources