一个ViewController调用另一个ViewController

时间:2017-11-14 17:29:09

标签: ios swift model-view-controller delegation

我有一个相当简单的应用程序,有三个viewControllers。你可以在下面看到它们:

Storyboard

我希望两个控制器在一段时间后切换回启动画面,但只要用户没有与应用程序交互。为此,我让它们都符合UITextFieldDelegate协议,因此我可以使用一些不同的委托函数来了解用户何时与文本字段交互。两个viewControllers都包含以下UITextFieldDelegate函数,并且都有一个变量segueTimer,我每次用户与文本字段交互时都会重置它:

我会尝试仅发布与问题相关的代码。

CheckInViewController

class CheckInViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var checkInView: CheckInView!

    var segueTimer: Timer?

    var fireTime = TimeInterval(20)

    var delegate: CheckInViewControllerDelegate!

    override func viewDidLoad(){

        super.viewDidLoad()

        checkInView.searchTextField.delegate = self

    }

    override func viewDidAppear(_ animated: Bool) {

        resetSegueTimer()
    }

    override func viewWillDisappear(_ animated: Bool) {

        deregisterFromKeyboardNotifications()
        //segueTimer?.invalidate()
        stopTimer()
    }


    func keyboardWillShow(sender: Notification){
        //print("keyboardWillShow()")

        ...

        resetSegueTime()
    }


    //This function fires everytime text changes
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        resetSegueTimer()

        return true
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {

        resetSegueTimer()

    }

    func textFieldDidEndEditing(_ textField: UITextField) {


    }

    func resetSegueTimer(){

        stopTimer()
        startTimer()

    }

    func startTimer(){
        print("@CheckInVC  startTimer() \(segueTimer)")
        if segueTimer == nil{
            segueTimer = Timer.scheduledTimer(timeInterval: fireTime, target: self, selector: #selector(unwindToSplash), userInfo: nil, repeats: false)
         }
    }

    func stopTimer(){
        print("@CheckInVC  stopTimer() \(segueTimer)")
        if segueTimer != nil {
            segueTimer!.invalidate()
            segueTimer = nil
        }
    }

    func unwindToSplash(){
        self.performSegue(withIdentifier: "UnwindViewControllers", sender: self)
    }

}

CheckInViewControllerDelegate

protocol CheckInViewControllerDelegate {
    var todaysGuests: NSMutableArray? { get set }
    var currentGuest: NSMutableDictionary? { get set }
    var guestRegisteredInKlik: Bool! { get set }
}

RegisterViewController

class RegisterViewController: UIViewController, CheckInViewControllerDelegate, UITextFieldDelegate {

    var segueTimer: Timer?
    var fireTime = TimeInterval(20)

    var currentGuest: NSMutableDictionary?
    var todaysGuests: NSMutableArray?
    var guestRegisteredInKlik: Bool!

    @IBOutlet weak var registerView: RegisterVisitorView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.registerView.companyTextField.delegate = self
        self.registerView.hostTextField.delegate = self
    {

    override func viewWillDisappear(_ animated: Bool) {

        registerView.nameLabel.text = ""
        registerView.companyTextField.text = ""
        registerView.hostTextField.text = ""

        stopTimer()
    }

    override func viewDidAppear(_ animated: Bool) {

        resetSegueTimer()

    }


    //delegate method to differntiate between multiple textfields that have the VC as their delegate
    func textField(_ textFieldToChange: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        if textFieldToChange == self.registerView.companyTextField {
            resetSegueTimer()

            return true

        } else if textFieldToChange == self.registerView.hostTextField {
            resetSegueTimer()

            return true
        }

        return true
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {

        resetSegueTimer()

    }

    func textFieldDidEndEditing(_ textField: UITextField) {

    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()

        return true
    }

    func resetSegueTimer(){

        stopTimer()
        startTimer()

    }

    func startTimer(){
        print("@RegisterVC  startTimer() \(segueTimer)")
        if segueTimer == nil{
            segueTimer = Timer.scheduledTimer(timeInterval: fireTime, target: self, selector: #selector(unwindViewControllers), userInfo: nil, repeats: false)
        }
    }

    func stopTimer(){
        print("@RegisterVC  stopTimer() \(segueTimer)")
        if segueTimer != nil {
            segueTimer!.invalidate()
            segueTimer = nil
        }
    }

}

我遇到的问题涉及最后两个viewControllers,一个是自定义类型CheckInViewController,另一个是RegisterViewController。我有两个委托方法的print语句,textFielDidBeginEditing,每个viewController一个。当我在RegisterViewController中并切换到另一个文本字段时,我看到第一个viewController的textFieldDidBeginEditing函数的print语句被调用而不是我所在的viewController的函数。

print语句只是向我显示了错误的行为。实际问题是当我在第二个viewController中更改textFields时,正在调用firstViewController的resetSegueTimer()函数。此外,在第二个viewController中调用的textField(shouldChangeCharactersIn range :)函数永远不会使其viewController中的segueTimer失效,因此当用户编辑文本字段时,不会重置回到启动画面的segue。

我认为这是一个问题,我使两个viewControllers符合相同的委托协议,同时也使第二个viewController成为第一个viewController的委托。但是,我不确定如何解决这个问题。

**编辑:将keyBoardWillShow()函数添加到CheckInViewController描述中,因为它导致了问题...该函数由RegisterViewController调用。但仍不确定如何。

1 个答案:

答案 0 :(得分:0)

通过在第一个viewController中从keyboardWillShow()中删除resetSegueTimer()来解决问题。这有两次调用resetSegueTimer,一次在keyboardWillShow中,然后再在EditingDidBegin中,它是多余的。当键盘弹出时,第二个viewController也会以某种方式调用此函数......仍然不确定这是怎么回事。

我认为这不是应用程序的最佳解决方案,OverD提供了更好的解决方案。最终会适用它。

相关问题