Swift:NSTimer,每次点击都会延迟隐藏UIButton

时间:2016-01-07 18:26:40

标签: swift uibutton hide nstimer

我有一个按钮(实际上是两个几乎相同的按钮),在另一个UIView中取消隐藏动作。

第二个UIView在第二个UIView结束后使用dispatch_after结束后2秒钟自动隐藏按钮,但是如果按钮在可见时被点击,我想保持按钮可见。这是timer属性和UIButton子类中的两个方法。我有一个@IBAction调用" justTapped"在ViewController中。

var timer = NSTimer()

func hideAndShrink(){
    if !self.hidden && !timer.valid{
        self.hidden = true
    }
}

func justTapped(){
    timer.invalidate()
    timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: "hideAndShrink", userInfo: nil, repeats: false)
}

点击任一按钮后,它们都不会隐藏。

在调用选择器中的方法时,计时器是否仍然有效?

得益于luk2302,答案是肯定的,定时器在发送选择器时有效

我怎样才能解决这个问题?

正如所建议的那样,我为计时器编写了第二种方法,它隐藏了没有!timer.valid的按钮?

事实证明我根本不需要第二种方法,因为我只是试图隐藏调用justTapped的按钮。这是两个按钮的扩展和缩小动画的最终代码。 self.direction是我希望按钮从下到上或从上到下展开的方向,并且还决定了背景图像。我认为这可能是一个列举,但我还没有想出那些。

    func unhideAndExpand(){

    if self.hidden{
        expand(self.frame.size.height)
    }

}

func hideAndShrink(){
    if !self.hidden && !shrinking{
        shrink(self.frame.size.height)
    }
}

func justTapped(){
    timer.invalidate()
    timer = NSTimer.scheduledTimerWithTimeInterval(3.0, target: self, selector: "hideAndShrink", userInfo: nil, repeats: false)
    }

func expand(height: CGFloat){

    if self.direction == "up"{
        self.transform = CGAffineTransformMake(1, 0, 0, 1/height, 1, height/2)
    } else if self.direction == "down" {
        self.transform = CGAffineTransformMake(1, 0, 0, 1/height, 1, -height/2)
    }
    self.hidden = false
    UIView.animateWithDuration(0.5, delay: 0, options: .CurveEaseOut, animations:
        {self.transform = CGAffineTransformIdentity}, completion: nil)
}

func shrink(height: CGFloat){
    self.shrinking = true
    UIView.animateWithDuration(0.5, delay: 0, options: .CurveEaseOut, animations:
        {if self.direction == "up"{
            self.transform = CGAffineTransformMake(1, 0, 0, 1/height, 1, height/2)
        } else if self.direction == "down" {
            self.transform = CGAffineTransformMake(1, 0, 0, 1/height, 1, -height/2)
            }
        }, completion: {_ in
            self.transform = CGAffineTransformIdentity
            self.hidden = true
            self.shrinking = false})
}

感谢大家的帮助。

2 个答案:

答案 0 :(得分:0)

您确定需要!timer.valid检查吗?如果hideAndShrink仅由计时器调用,则您似乎可以将其更改为

func hideAndShrink(){
    self.hidden = true
}
只有在计时器未失效时才会调用

hideAndShrink,因此您可以跳过此检查。

答案 1 :(得分:0)

  

在调用选择器中的方法时,计时器是否仍然有效?

是的,它是

以下是一个完整的可运行游乐场示例,展示了:

import Foundation
import XCPlayground    
XCPSetExecutionShouldContinueIndefinitely()

class Bla {
    var timer : NSTimer?

    init() {
        timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "check", userInfo: nil, repeats: false)

        NSTimer.scheduledTimerWithTimeInterval(1.1, target: self, selector: "checkAgain", userInfo: nil, repeats: false)
    }

    @objc func check(){
        print(timer!.valid)
    }

    @objc func checkAgain(){
        check()
    }
}

let bla = Bla()

这将首先输出true,然后输出false。 触发时,计时器仍然有效。一旦你离开被解雇的方法,计时器就会失效。

这将使您的if无效,因为该方法在计时器触发时无效,因为anything && !true评估为false

如何绕过该问题,可以创建一种不同的方法timerFired,它可以设置您班级的某些内部属性,例如var timerHasFired = falsetrue。你的``那么必须检查那个变量而不是计时器:

var timer = NSTimer()
var timerHasFired = false

func hideAndShrink(){
    if !self.hidden && hideAndShrink {
        self.hidden = true
    }
}

func timerFired() {
    timerHasFired = true
    hideAndShrink()
}

func justTapped(){
    timer.invalidate()
    timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: "timerFired", userInfo: nil, repeats: false)
}