如何在解除第二个控制器后调用第一个控制器中的函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在解除第二个控制器后调用第一个控制器中的函数相关的知识,希望对你有一定的参考价值。

我有两个UIViewController,当我点击一个按钮时,它从第一个视图控制器转到第二个视图控制器。在那之前,我让UIView动画到另一个地方。在关闭第二个View Controller之后,我想将第一个视图控制器中的UIView移回原来的位置。但是,当我从第二个视图控制器调用一个函数在第一个视图控制器中取消第二个视图控制器动画UIview后,它无法获取UIView的属性,并且无法对其进行任何操作。我想因为第一个UIViewController尚未加载。那是问题吗?我该如何解决这个问题?

答案

有两种解决方案可以使用快速闭包

class FirstViewController: UIViewController {

      @IBAction func start(_ sender: Any) {
           guard let secondController = self.storyboard?.instantiateViewController(withIdentifier: "SecondController") as? SecondController else { return }
        secondController.callbackClosure = { [weak self] in
            print("Do your stuff")
        }
        self.navigationController?.pushViewController(secondController, animated: true)
       }
}
//----------------------------

class SecondController: UIViewController {

      var callbackClosure: ((Void) -> Void)?

      override func viewWillDisappear(_ animated: Bool) {
         callbackClosure?()
          }
 }

或者您可以使用协议

class FirstViewController: UIViewController {

@IBAction func start(_ sender: Any) {
       guard let secondController = self.storyboard?.instantiateViewController(withIdentifier: "SecondController") as? SecondController else { return }
        secondController.delegate = self
    self.navigationController?.pushViewController(secondController, animated: true)
   }    

}

extension ViewController : ViewControllerSecDelegate {

    func didBackButtonPressed(){
         print("Do your stuff")
    }
}
//--------------------------


protocol SecondControllerDelegate : NSObjectProtocol {
    func didBackButtonPressed()
}

class SecondController: UIViewController {

    weak var delegate: SecondControllerDelegate?

         override func viewWillDisappear(_ animated: Bool) {
              delegate?.didBackButtonPressed()
         }
 }
另一答案

你可以尝试使用一个闭包。像这样的东西:

class FirstViewController: UIViewController {

    @IBOutlet weak var nextControllerButton: UIButton!
    private let animatableView: UIView = UIView()

    private func methodsForSomeAnimation() {
        /* 
         perform some animation with 'animatableView'
        */
    }

    @IBAction func nextControllerButtonAction() {
        // you can choose any other way to initialize controller :)
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        guard let secondController = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController else { return }
        secondController.callbackClosure = { [weak self] in
            self?.methodsForSomeAnimation()
        }
        present(secondController, animated: true, completion: nil)
    }
}

class SecondViewController: UIViewController {

    @IBOutlet weak var dismissButton: UIButton!
    var callbackClosure: ((Void) -> Void)?

    @IBAction func dismissButtonAction() {
        callbackClosure?()
        dismiss(animated: true, completion: nil)
        /* 
         or you call 'callbackClosure' in dismiss completion
         dismiss(animated: true) { [weak self] in
             self?.callbackClosure?()
         }
        */
    }

}
另一答案

当您呈现第二个视图控制器时,您可以传递第一个视图控制器的实例。

第二个VC可以保存第一个VC的实例,如下所示:

weak var firstViewController: NameOfController?

那么当你呈现第二个VC时,请确保你设置了值,所以它不是这样的:

firstViewController = self

完成此操作后,您将能够访问该viewControllers函数。

另一答案

当你说它无法获得UIView的属性时,因为你把它作为私有?为什么在转到第二个ViewController之前,它在第一个控制器消失之前不会替换你的UIView。我认为这是一个必须清理视图控制器状态才能进一步进入第二个视图控制器的情况。

通过Apple文档检查ios生命周期方法:viewWillDisappearviewDidDisappear,然后使用其中一种方法执行动画。

另一答案

iOS 11.x Swift 4.0

在调用VC时你放了这个代码......

private struct Constants {
    static let ScannerViewController = "Scan VC"
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
 if segue.identifier == Constants.ScannerViewController {
        let svc = destination as? ScannerViewController
        svc?.firstViewController = self
    }
}

你在我的案例“扫描VC”中命名segue的地方,这就是它在Xcode面板中的样子。

enter image description here

现在在扫描VC中,我们在类声明下得到了它

weak var firstViewController: HiddingViewController?

现在稍后在您的代码中,当您准备返回时,我只需在我的firstViewController中设置我关注的变量,就像这样......

self.firstViewController?.globalUUID = code

我在HiddingViewController中设置了这样的...

var globalUUID: String? {
    didSet {
        startScanning()
    }
}

所以基本上当我关闭扫描VC时,我设置了变量globalUUID,它在这里开始扫描方法。

另一答案

实际上非常简单的解决方案......只需将动画放入viewDidAppear方法即可。每次加载视图时都会调用此方法。

class firstViewController: UIViewController {

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // insert animation here to run when FirstViewController appears...
    }
}

以上是关于如何在解除第二个控制器后调用第一个控制器中的函数的主要内容,如果未能解决你的问题,请参考以下文章

模态转换后解除分配 SKScene

堆叠 presentViewController 后 statusBarFrame = 0

当模态视图控制器被解除时如何调用函数

如何在快速关闭第二个视图控制器后启用带有视图的自定义视图控制器

启动第二个视图控制器后如何关闭父视图控制器?

关闭 Popover 后更新第一个视图