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

时间:2017-10-22 08:00:52

标签: ios swift uiviewcontroller

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

6 个答案:

答案 0 :(得分:3)

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

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()
         }
 }

答案 1 :(得分:1)

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

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

weak var firstViewController: NameOfController?

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

firstViewController = self

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

答案 2 :(得分:1)

您可以尝试使用闭包。像这样:

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?()
         }
        */
    }

}

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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
    }
}

在我的案例中将segue命名为“ Scan VC”的地方,这就是Xcode面板中的样子。

enter image description here

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

weak var firstViewController: HiddingViewController?

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

self.firstViewController?.globalUUID = code

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

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

因此,基本上,当我关闭扫描VC时,我设置了变量globalUUID,这将在这里启动扫描方法。

答案 5 :(得分:0)

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

pwd