简体   繁体   中英

Swift | Dismiss ViewController and Push other ViewController

Solved it: I forgot to declare tvx.selectionDelegate = self in VC1, thats why it never executed

I'v searched very long and fund two similar answers to my problem online: here

But all of them work with dismissing and then presenting another view, and I want to dismiss and PUSH another ViewC.

I have 3 ViewController:

VC1 lets Call it: DownloadsViewController

VC2 lets Call it: SelectActionController

VC3 lets Call it: fileInfoView

VC1 presents VC2 modally then VC2 should dismiss and VC1 should PUSH VC3 immediately.


I've tried:

VC2:

self.present(vx, animated: true, completion: nil) 

and the to put the PUSH animation in completion {} but it crashes.


The next thing I've tried is to make a delegate and if I press a button on VC2 it call VC1 to dismiss VC2 and Push VC3. Like Here:

VC2:

protocol PushViewControllerDelegate: class {
func pushViewController(_ controller: UIViewController)
}

class SelectActionController: UIViewController, UITableViewDelegate, UITableViewDataSource {
weak var delegate: PushViewControllerDelegate?

public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{

    if self.delegate != nil {
        self.delegate?.pushViewController(self)}

VC1:

func pushViewController(_ controller: UIViewController) {

        controller.dismiss(animated: true) { () -> Void in

            self.performSegue(withIdentifier: self.segue2, sender: nil)

            //let vx = self.storyboard?.instantiateViewController(withIdentifier: "FileInfo") as! fileInfoView
            //self.navigationController?.pushViewController(vx, animated: false)

        }
    }

The Trird thing I tried was to make a global Variable and if it dismisses, just set a Bool variable to true and an func in VC1 should recognize it(my intention). Only problem it doesn't regognize dismissing as ViewDidAppear or stuff like that.


So none of that worked.

Does anyone has an Idea to this?

EDITED after OP comment

Just use a protocol. Let your first controller adopt it, and add the required function. Set a protocol variable in the second controller who takes the first one for reference and call the function when you dismiss the second controller. You can now use the dismiss function to do whatever you want, pass data, send to an other controller...

first view controller :

protocol CustomProtocol {
    func dismissed()
}

class AViewController: UIViewController, CustomProtocol {

    @IBOutlet weak var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func toVC2(_ sender: UIButton) {
        let VC = self.storyboard!.instantiateViewController(withIdentifier: "BViewController") as! BViewController
        VC.customProtocol = self
        VC.view.backgroundColor = .white
        self.present(VC, animated: true, completion: nil)
    }

    func dismissed() {
        let yourViewController = UIViewController()
        yourViewController.view.backgroundColor = .red
        guard let navigationController = self.navigationController else {return}
        navigationController.pushViewController(yourViewController, animated: true)
    }
}

second view controller :

class BViewController: UIViewController {

    var customProtocol: CustomProtocol?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func quit(_ sender: UIButton) {
        self.dismiss(animated: true) {
            guard let proto = self.customProtocol else {return}
            proto.dismissed()
        }
    }
}

I hope you need to perform the dismiss action on your

public func tableView(_ tableView: UITableView, didSelectRowAt indexPath:

in "SelectActionController" right ?

In such case you have to do as follows,

public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

if self.delegate != nil {
     dismiss(animated: true) {
        self.delegate?.pushViewController(self)}
    }
}

I have shared an example project related to your situation, please refer it. https://github.com/Bharath-MallowTech/StackoverflowSolutions/tree/master/viewcontrollerDismissAndPush

Could you post some code on what you've been trying? What is self here? Is it VC1 , VC2 or VC3 ?

What you could do is have a look at protocols, so you use VC1 as a delegate and when you dismiss VC2 it will also call it's delegate showVC3() . You then place that delegate.showVC3() in the completion block for your dismiss .

// Declare it in VC1
@protocol MyDelegate {
    func showVC3()
}

class VC1: UIViewController, MyDelegate {
    var vc2: VC2ViewController = VC2ViewController()
    var vc3: VC3ViewController = VC3ViewController()

    func showVC2() {
        vc2.delegate = self
        self.present(self.vc2)
    }

    func showVC3() {
        self.present(self.vc3)
    }
}

// In VC2
class VC2: UIViewController {
    var delegate: MyDelegate?

    func closeVC2() {
        self.dismiss(animated: true, completion: {
            self.delegate?.showVC3()
        })
    }
}

Not sure if this works, haven't tried it out since I'm on my PC at the moment. But change it according to your needs and test it out.

According to your File from Github, I think you forgot to declare

tvx.selectionDelegate = self

in the

func imagePressed

Even i had the same situation , that after presenting a view controller , i need to push to some other view controller. If we have vc1, vc2, vc3, We presented vc2 from vc1, then on button click of vc2 we need to push to vc3, what i did is, i set vc3 as root view controller. You can check code as per below.

func goToHomeScreenPage(transition : Bool)
{
    let _navigation : UINavigationController!

    let startVC : TabbarViewController = Utilities.viewController(name: "TabbarViewController", onStoryboard: StoryboardName.Login.rawValue) as! TabbarViewController

    _navigation = UINavigationController(rootViewController: startVC)

    _navigation.setNavigationBarHidden(true, animated: true)

    let transitionOption = transition ? UIViewAnimationOptions.transitionFlipFromLeft : UIViewAnimationOptions.transitionFlipFromLeft
    gotoViewController(viewController: _navigation, transition: transitionOption)

}

the above method gotoviewcontroller() is below,

func gotoViewController(viewController: UIViewController, transition: UIViewAnimationOptions)
{
    if transition != UIViewAnimationOptions.transitionCurlUp
    {
        UIView.transition(with: self.window!, duration: 0.5, options: transition, animations: { () -> Void in
            self.window!.rootViewController = viewController
        }, completion: { (finished: Bool) -> Void in
            // do nothing
        })
    } else {
        window!.rootViewController = viewController
    }
}

Declare var window: UIWindow? on top, you can write these methods in appdelegate and call them by creating appdelegate instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM