【问题标题】:performSegueWithIdentifier pushes two ViewControllers when pressed 2x fastperformSegueWithIdentifier 在快速按下 2 倍时推送两个 ViewController
【发布时间】:2015-10-06 10:17:18
【问题描述】:

当我有时需要使用 performSegueWithIdentifier 时,我有一个复杂的应用程序。我不能用 IB 触发器替换它,必须以编程方式完成!有时我在 UIButton 的操作中甚至在委托方法中将它们称为 collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)

问题是,如果我两次快速触发事件,例如通过双击 UIButton,我会将 destinationViewController 两次推送到 navigationController 的堆栈中,这不是我想要的。我只希望它被推送一次。 prepareforSegue 也被调用了两次。

例子:

func addDeal(sender: UIBarButtonItem) {
    self.performSegueWithIdentifier("segueDeal", sender: sender)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if(segue.identifier == "segueDeal") {
        (segue.destinationViewController as! DealVC).deal = self.deal
    }
}

【问题讨论】:

  • 从标签中删除目标 c,因为您的问题只涉及 swift 语言
  • 你在prepareForSegue做什么?
  • 是swift还是Objective-C对我来说无关紧要。我只是想要一种优雅的方式来做到这一点
  • @Paulw11 添加了prepareForSegue

标签: ios objective-c iphone swift


【解决方案1】:

在调用此方法时禁用按钮,这将防止它被多次点击。

func addDeal(sender: UIBarButtonItem) {
    sender.enabled = false
    self.performSegueWithIdentifier("segueAddDeal", sender: sender)
}

当您的视图重新出现时,您还必须重新启用它例如:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    someReferenceToTheButton.enabled = true
}

脑筋急转弯

我刚刚在一个示例项目中将其作为requested in the comments 的“更通用的方式”组合在一起。如图所示,它在基本用例中“工作”,但老实说,我不知道它是否能在更复杂的情况下工作。我对它也不是特别满意,感觉很老套和脆弱。

class ViewController: UIViewController {

    private var preparingForSegue = false

    override func viewWillAppear(animated: Bool) {
        preparingForSegue = false
        super.viewWillAppear(animated)
    }

    @IBAction func pushOn(sender: AnyObject) {
        // Provided as an example of an attempt to perform 2 segues in quick succession
        self.performSegueWithIdentifier("DoPush", sender: self)
        self.performSegueWithIdentifier("DoPush", sender: self)
    }

    override func performSegueWithIdentifier(identifier: String, sender: AnyObject?) {
        if !preparingForSegue {
            super.performSegueWithIdentifier(identifier, sender: sender)
        }
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        super.prepareForSegue(segue, sender: sender)
        preparingForSegue = true
    }

}

【讨论】:

  • 这肯定会起作用,但我一直在寻找一种更通用的方法来防止这种行为,而不必禁用/启用我这样做的每个 viewController 中的按钮
  • @Jdmoreira 检查我的更新答案,但请谨慎使用:)
  • 我喜欢!我会尽快尝试的。应该在所有用例中都能很好地工作!谢谢
【解决方案2】:

对我来说,这个方法很有帮助:

override func shouldPerformSegueWithIdentifier(identifier: String?, sender: AnyObject?) -> Bool {
  for window in UIApplication.sharedApplication().windows {
    if let window = window as? UIWindow {
      if let sub = window.subviews.first as? UIAlertView {
        return false
      }
    }
  }
  return navigationController?.topViewController == self
}

我只是将此方法移至 RootViewController,我的主层次结构中的每个控制器都继承自它。请注意,在方法中,我还要检查是否有 UIAlertView 呈现。

【讨论】:

  • @Jdmoreira,它检查堆栈中的顶部控制器是否与尝试执行 segue 的控制器相同。此方法在控制器执行某些 segue 之前调用,您可以指定是否应该执行它
  • 这是一个很好的解决方案!谢谢
【解决方案3】:

最好删除按钮上的TouchUp Inside。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-30
    • 2017-07-21
    • 1970-01-01
    • 2016-12-28
    • 2013-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多