我有一个显示视图的按钮,该按钮在指定的时间间隔后自动消失。现在,如果在该视图已经可见的情况下再次按下该按钮,则它应该消失并显示一个新视图,并且重置新视图的计时器。

在按钮上按我有以下代码:

func showToast() {
    timer?.invalidate()
    timer = nil

    removeToast()

    var appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    var toAddView = appDelegate.window!

    toastView = UIView(frame: CGRectMake(0, toAddView.frame.height, toAddView.frame.width, 48))
    toastView.backgroundColor = UIColor.darkGrayColor()
    toAddView.addSubview(toastView)

    timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: Selector("removeToast"), userInfo: nil, repeats: false)

    UIView.animateWithDuration(0.5, animations: { () -> Void in
        self.toastView.frame.origin.y -= 48
    })
}

要删除烤面包,我有以下代码:
func removeToast() {
    if toastView != nil {
        UIView.animateWithDuration(0.5,
            animations: { () -> Void in
                self.toastView.frame.origin.y += 48
            },
            completion: {(completed: Bool) -> Void in
                self.toastView.removeFromSuperview()
                self.toastView = nil
            })
    }
}

现在,即使每次通过执行timer.invalidate()重置计时器,我也会在removeToast()中收到两个调用,这会删除新插入的视图。可能是UIView.animate引起问题,我没有得到如何调试removeToast()的两个回调。一个演示行为的演示项目是here

注意:我确实找到了一些帖子,说要使用dispatch_after()而不是计时器,这也是@ jervine10的要求,但它不足以解决我的问题。就像我使用dispatch_after一样,很难使GCD调用无效。 NSTimers是否可以完成某些工作。我认为NSTimers是为此目的而设计的,我做错了什么。

最佳答案

对不起,您没有看到您的示例项目,也感谢您指导我进行操作。我可以清楚地看到问题出在哪里,解决方案非常简单。更改为此删除土司:

func removeToast() {

    guard let toastView = self.toastView else {
        return
    }

    UIView.animateWithDuration(0.1,
        animations: { () -> Void in
            toastView.frame.origin.y += 48
        },
        completion: {(completed: Bool) -> Void in
            toastView.removeFromSuperview()

            if self.toastView == toastView {
                self.toastView = nil
            }
        })
}

基本上,问题在于您是在动画块中捕获self,而不是toastView。因此,一旦动画块异步执行,它们将删除上一个函数中设置的新toastView

该解决方案很简单,并且还解决了可能的竞争条件,那就是将toastView捕获到一个变量中。最后,我们检查实例变量是否等于要删除的视图,然后将其无效。

提示:考虑对weak使用toastView参考

09-19 20:38