【问题标题】:One ViewController calling delegated method of another ViewController一个 ViewController 调用另一个 ViewController 的委托方法
【发布时间】:2018-04-27 18:15:55
【问题描述】:

我有一个相当简单的应用程序,其中包含三个视图控制器。你可以在下面看到它们:

我希望两个控制器在一段时间后重新回到启动屏幕,但前提是用户不与应用交互。为此,我让它们都符合 UITextFieldDelegate 协议,因此我可以使用一些不同的委托函数来了解用户何时与文本字段交互。两个 viewController 都包含以下 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
        }
    }

}

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

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

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

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

【问题讨论】:

  • 让我了解您要完成的工作...当我在任何 ViewController 中的计时器到期时,您想反驳启动 viewController ?
  • 首先,delegate var 应该是弱引用。
  • @OverD 是的,当计时器到期时,我想继续使用 Splash,但我希望每次有人与文本字段交互时重置计时器,让用户有时间在文本字段中输入文本。但是假设他们离开了应用程序,我希望它恢复到第一个 viewController。
  • 创建一个自定义类,确认 uitextfielddelegate 并在该类中设置计时器逻辑,而不是重复您的代码。计时器到期后,将您的启动视图控制器设置为根视图控制器并导航到它。或者您可以将视图控制器嵌入导航视图控制器并将其弹出到根视图控制器。

标签: ios swift model-view-controller delegation


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-26
    • 2012-10-03
    • 1970-01-01
    • 2016-05-06
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    • 2012-05-10
    相关资源
    最近更新 更多