Swift – Using popViewController and passing data to the ViewController you're returning to

后端 未结 4 1417
孤街浪徒
孤街浪徒 2021-01-12 03:45

I have an optional bool variable called showSettings on my first view controller which is called ViewController, and I\'m popping from

相关标签:
4条回答
  • 2021-01-12 03:59
    _ = self.navigationController?.popViewController(animated: true)
            let previousViewController = self.navigationController?.viewControllers.last as! PreviousViewController
            previousViewController.PropertyOrMethod
    
    0 讨论(0)
  • 2021-01-12 04:01

    So I figured it out, based mostly from this post – http://makeapppie.com/2014/09/15/swift-swift-programmatic-navigation-view-controllers-in-swift/

    In SecondViewController, above the class declaration, add this code:

    protocol SecondVCDelegate {
        func didFinishSecondVC(controller: SecondViewController)
    }
    

    Then inside of SecondViewContoller add a class variable:

    var delegate: MeditationVCDelegate! = nil

    Then inside of your function that your button targets, add this:

    self.navigationController?.popViewControllerAnimated(true)
    delegate.didFinishSecondVC(self)
    

    What we're doing here is doing the pop in SecondViewController, and not passing any data, but since we've defined a protocol, we're going to use that in ViewController to handle the data.

    So next, in ViewController, add the protocol you defined in SecondViewController to the list of classes ViewController inherits from:

    class ViewController: UIViewController, SecondVCDelegate { ... your code... }
    

    You'll need to add the function we defined in the new protocol in order to make the compiler happy. Inside of ViewController's class, add this:

    func didFinishSecondVC(controller: SecondViewController) {
        self.myBoolVar = true
        controller.navigationController?.popViewControllerAnimated(true)
    }
    

    In SecondViewController where we're calling didFinishSecondVC, we're calling this method inside of the ViewController class, the controller we're popping to. It's similar to if we wrote this code inside of SecondViewController but we've written it inside of ViewController and we're using a delegate to manage the messaging between the two.

    Finally, in ViewController, in the function we're targeting to push to SecondViewController, add this code:

    let secondVC = secondViewController()
    secondVC.delegate = self
    self.navigationController?.pushViewController(secondVC, animated: true)
    

    That's it! You should be all set to pass code between two view controllers without using storyboards!

    0 讨论(0)
  • 2021-01-12 04:09

    Expanding upon the answer by Abdul Baseer Khan:

    For cases where the current view controller may have been loaded by different types of previous view controller, we can use the safer as? call instead of as!, which will return nil if the controller is not what we were looking for:

    let previousVC = self.navigationController?.viewControllers.last as? AnExampleController
    previousVC?.doSomething()
    

    Although, you would need to repeat that for each different view controller that could load the current view controller.

    So, you may want to, instead, implement a protocol to be assigned to all the possible previous view controllers:

    protocol PreviousController: UIViewController {
      func doSomething()
    }
    
    class AnExampleController: UIViewController, PreviousController {
      // ...
      func doSomething() {}
    }
    
    class AnotherController: UIViewController, PreviousController {
      // ...
      func doSomething() {}
    }
    
    class CurrentController: UIViewController {
      // ...
      func goBack() {
        let previousVC = self.navigationController?.viewControllers.last as? PreviousController
        previousVC?.doSomething()
      }
    }
    
    0 讨论(0)
  • 2021-01-12 04:22

    I came across this while looking for a way to do it. Since I use Storyboards more often, I found that I can get the array of controllers in the navigation stack, get the one just before the current one that's on top, check to see if it's my delegate, and if so, cast it as the delegate, set my methods, then pop myself from the stack. Although the code is in ObjC, it should be easily translatable to swift:

    // we need to get the previous view controller
    NSArray *array = self.navigationController.viewControllers;
    if ( array.count > 1) {
        UIViewController *controller = [array objectAtIndex:(array.count - 2)];
        if ( [controller conformsToProtocol:@protocol(GenreSelectionDelegate)]) {
            id<GenreSelectionDelegate> genreDelegate = (id<GenreSelectionDelegate>)controller;
            [genreDelegate setGenre:_selectedGenre];
        }
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    0 讨论(0)
提交回复
热议问题