0

I would like to know how can I push user back to specific ViewController from regular swift class without being non UIView Class

Example

class nonUI {
 function Push() {
  //How to send user back to specific VC here?
 }
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579

3 Answers3

1

This is a generic method you can use with in the class or outside the class for push if required else it will pop if the instance of view controller is in the stack:

func pushIfRequired(className:AnyClass) {

    if (UIViewController.self != className) {
        print("Your pushed class must be child of UIViewController")
        return
    }
    let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    var isPopDone = false
    let mainNavigation = UIApplication.shared.delegate?.window??.rootViewController as? UINavigationController
    let viewControllers = mainNavigation!.viewControllers
    for vc in viewControllers {
        if (type(of: vc) == className) {
            mainNavigation?.popToViewController(vc, animated: true)
            isPopDone =  true
            break
        }
    }
    if isPopDone == false{
        let instanceSignUp = storyboard.instantiateViewController(withIdentifier: NSStringFromClass(className)) // Identifier must be same name as class
        mainNavigation?.pushViewController(instanceSignUp, animated: true)
    }
}

USES

pushIfRequired(className: SignupVC.self)
Salman Ghumsani
  • 3,647
  • 2
  • 21
  • 34
1

You could also utilise the NotificationCenter to achieve a loosely coupled way to "request a view controller"; if you will.

For example, create a custom UINavigationController that observes for the custom Notification and upon receiving one, looks for the requested UIViewController and pops back to it.

class MyNavigationController : UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(forName: NSNotification.Name("RequestViewController"), object: nil, queue: OperationQueue.main) { [unowned self] (note) in
            guard let targetType = note.object as? UIViewController.Type else {
                print("Please provide the type of the VC to display as an `object` for the notification")
                return
            }

            // Find the first VC of the requested type
            if let targetVC = self.viewControllers.first(where: { $0.isMember(of: targetType) }) {
                self.popToViewController(targetVC, animated: true)
            }
            else {
                // do what needs to be done? Maybe instantiate a new object and push it?
            }
        }
    }
}

Then in the object you want to go back to a specific ViewController, post the notification.

@IBAction func showViewController(_ sender: Any) {
    NotificationCenter.default.post(Notification(name: NSNotification.Name("RequestViewController"), object: ViewController2.self))
}

Now, it's also fairly easy to adopt this method for other presentation-styles. Instead of using the NotificationCenter, you could also muster up a Mediator to achieve the loose coupling.

fguchelaar
  • 4,779
  • 23
  • 36
  • It did not work exactly that way, but your suggest was the best out here. simple I added Notification and passed to function in UI Class and from there performed the transaction and from Non UI Class called that notification. Thanks for the idea! – Elvin Mammadov Aug 14 '17 at 06:11
0

You can't. UIViewController and its subclass only can handle navigate between screen.

In your case, need pass link (variable) to navigation controller in custom class.

Like:

class nonUI {
    var navigationController: UINavigationController?

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

 function Push() {
  //How to send user back to specific VC here?
  navigationController?.popViewController(animated: true)
 }
}
Citrael
  • 542
  • 4
  • 17