Swift2:TKSubmitTransitionButton。当用户登录/注册不正确时,如何停止按钮的转换/动画

Posted

技术标签:

【中文标题】Swift2:TKSubmitTransitionButton。当用户登录/注册不正确时,如何停止按钮的转换/动画【英文标题】:Swift2: TKSubmitTransitionButton. How do i stop a button from transition/ animating when user login/ signup are incorrect 【发布时间】:2016-03-31 09:32:27 【问题描述】:

我已经尝试了很多次,我得到的最好的结果是,无论我使用什么命令,都会有一个永远不会取消或停止的动画。

在遵循@Mattias 示例之后,我更新了我的代码,看起来像这样:

   // DESIGN ANIMATION... TKTRANSITIONSUBMITBUTTON
@IBOutlet weak var btnFromNib: TKTransitionSubmitButton!

@IBAction func onTapButton(sender: AnyObject) 
    btnFromNib.startLoadingAnimation()

        if let email = self.emailField.text where email != "", let password = self.passwordField.text where password != "" 

            DataService.ds.REF_BASE.authUser(email, password: password, withCompletionBlock:  error, authData in
                if error != nil 

                    self.btnFromNib.returnToOriginalState()
                    if error.code == STATUS_ACCOUNT_NONEXIST 

                        self.showErrorAlert("This User does not exist", msg: "Please Sign Up")
                     else 

                    

                 else 
                    self.btnFromNib.startFinishAnimation(1, completion: 
                        let myTabbarController = self.storyboard?.instantiateViewControllerWithIdentifier("myTabbarController") as! UITabBarController
                        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
                        appDelegate.window?.rootViewController = myTabbarController

                        myTabbarController.transitioningDelegate = self
                    )

                
            )
           

按钮仍在不停地旋转/动画。检查自定义动画类后,该函数继承自:

     public func startLoadingAnimation() 
    self.cachedTitle = titleForState(.Normal)
    self.setTitle("", forState: .Normal)
    self.shrink()
    NSTimer.schedule(delay: shrinkDuration - 0.25)  timer in
        self.spiner.animation()
    


public func startFinishAnimation(delay: NSTimeInterval, completion:(()->())?) 
    NSTimer.schedule(delay: delay)  timer in
        self.didEndFinishAnimation = completion
        self.expand()
        self.spiner.stopAnimation()
    


public func animate(duration: NSTimeInterval, completion:(()->())?) 
    startLoadingAnimation()
    startFinishAnimation(duration, completion: completion)


public override func animationDidStop(anim: CAAnimation, finished flag: Bool) 
    let a = anim as! CABasicAnimation
    if a.keyPath == "transform.scale" 
        didEndFinishAnimation?()
        NSTimer.schedule(delay: 1)  timer in
            self.returnToOriginalState()
        
    


func returnToOriginalState() 
    self.layer.removeAllAnimations()
    self.setTitle(self.cachedTitle, forState: .Normal)

我注意到它有一个公共覆盖 func animationDidStop(anim: CAAnimation, finished: Bool) 作为停止动画的函数。但是当我使用它时,我得到了这个错误!

我如何正确地让它工作? ...

提前致谢

** 更新问题**

【问题讨论】:

【参考方案1】:

我检查了TKTransitionSubmitButton 的代码,其中有名为startLoadingAnimation()returnToOriginalState()startFinishAnimation() 的公共方法。

我建议:

Button tapped
startLoadingAnimation()
Check credentials
    If wrong/error: returnToOriginalState()
    If correct: startFinishAnimation()

转换,来自TKTransitionSubmitButton 文档:

btn.startFinishAnimation 
    //Your Transition
    let secondVC = SecondViewController()
    secondVC.transitioningDelegate = self
    self.presentViewController(secondVC, animated: true, completion: nil)

编辑:据我所知,该课程的.animate() 调用了开始和结束动画,这就是你不能取消它的原因。

EDIT2这对我来说是有效的(但我不确定静态cornerRadius)

import UIKit

class ViewController: UIViewController 

@IBOutlet weak var submitButton: TKTransitionSubmitButton!

override func viewDidLoad() 
    super.viewDidLoad()
    submitButton.layer.cornerRadius = 15
    // Do any additional setup after loading the view, typically from a nib.


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.


@IBAction func buttonPressed(sender: AnyObject) 

    submitButton.startLoadingAnimation()

    delay(2, closure: 

        self.checkCredentials()

    )




func checkCredentials()

    //FAKING WRONG CREDENTIALS
    let userAndPasswordCorrect = false

    if !userAndPasswordCorrect
    
        submitButton.returnToOriginalState()
        //Alert or whatever
    


//Faking network delay
func delay(delay:Double, closure:()->()) 
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)


【讨论】:

可以帮我写出代码吗? .. returnToOriginalState() 不是公共函数,即使我成功了,也会出错。使用你的方法有点令人困惑,尽管它很有意义 当我调用 returnToOriginalState() 函数时,它并没有取消动画。相反,它一直在旋转。看到 animationDidStop(anim: CAAnimation, finished: Bool) 确实调用了 returnToOriginalState()。但我无法编写代码来让它工作。 我会全力以赴的! 更新的答案,为我工作。祝你好运! (而且这些方法对我都是公开的,我没有更改按钮类中的任何内容) 我已经更新了这个问题。我通过更多的调整尝试了你的方式很多次,但不明白为什么它不起作用。我的猜测是,如果我能够成功地调用公共覆盖函数 animationDidStop(anim: CAAnimation, finished flag: Bool),我会成功地让它停止动画。抱歉打扰了。谢谢【参考方案2】:

我检查了TKTransitionSubmitButton的代码。

我解决了这个问题。请尝试在 DispatchQueue.main.async 下停止动画并正常工作。

 'func apicallforLogin()  
            let urlString = "http://"
            guard let requestUrl = URL(string:urlString) else  return 
            let request = URLRequest(url:requestUrl)
            let task = URLSession.shared.dataTask(with: request) 
                (data, response, error) in
                if error == nil,let usableData = data 
                    DispatchQueue.main.async 
                        self.btnLogin.startFinishAnimation(0.1, completion: 
                            let HomeVC = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
                            HomeVC.transitioningDelegate = self
                            self.navigationController?.pushViewController(HomeVC, animated: false)
                        )
                    
                    print(usableData)
                else
                    DispatchQueue.main.async 
                        self.btnLogin.returnToOriginalState()
                    
                
            
            task.resume()'

【讨论】:

【参考方案3】:

好吧,您现在可能已经得到了答案,但我只想给出我的答案。你可以复制下面的代码,一切都会好起来的。我已做出更改并为此问题创建了拉取请求。

import Foundation
import UIKit

@IBDesignable
open class TKTransitionSubmitButton : UIButton, UIViewControllerTransitioningDelegate, CAAnimationDelegate 

    lazy var spiner: SpinerLayer! = 
        let s = SpinerLayer(frame: self.frame)
        return s
    ()

    @IBInspectable open var spinnerColor: UIColor = UIColor.white 
        didSet 
            spiner.spinnerColor = spinnerColor
        
    

    open var didEndFinishAnimation : (()->())? = nil

    let springGoEase = CAMediaTimingFunction(controlPoints: 0.45, -0.36, 0.44, 0.92)
    let shrinkCurve = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    let expandCurve = CAMediaTimingFunction(controlPoints: 0.95, 0.02, 1, 0.05)
    let shrinkDuration: CFTimeInterval  = 0.1
    @IBInspectable open var normalCornerRadius:CGFloat = 0.0 
        didSet 
            self.layer.cornerRadius = normalCornerRadius
        
    

    var cachedTitle: String?
    var isAnimating = false

    public override init(frame: CGRect) 
        super.init(frame: frame)
        self.setup()
    

    public required init!(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)!
        self.setup()
    

    func setup() 
        self.clipsToBounds = true
        spiner.spinnerColor = spinnerColor
    

    open func startLoadingAnimation() 
        self.isAnimating = true
        self.cachedTitle = title(for: UIControlState())
        self.setTitle("", for: UIControlState())
        self.layer.addSublayer(spiner)

        // Animate
        self.cornerRadius()
        self.shrink()
        _ = Timer.schedule(delay: self.shrinkDuration - 0.25)  timer in
            self.spiner.animation()
        
    

    open func startFinishAnimation(_ delay: TimeInterval,_ animation: CAMediaTimingFunction, completion:(()->())?) 
        self.isAnimating = true
        _ = Timer.schedule(delay: delay)  timer in
            self.didEndFinishAnimation = completion
            self.expand(animation)
            self.spiner.stopAnimation()
        
    

    open func animate(_ duration: TimeInterval,_ animation: CAMediaTimingFunction, completion:(()->())?) 
        startLoadingAnimation()
        startFinishAnimation(duration, animation, completion: completion)
    

    open func setOriginalState() 
        self.returnToOriginalState()
        self.spiner.stopAnimation()
    

    public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) 
        let a = anim as! CABasicAnimation
        if a.keyPath == "transform.scale" 
            didEndFinishAnimation?()
            _ = Timer.schedule(delay: 1)  timer in
                self.returnToOriginalState()
            
        
    

    open func returnToOriginalState() 
        self.spiner.removeFromSuperlayer()
        self.layer.removeAllAnimations()
        self.setTitle(self.cachedTitle, for: UIControlState())
        self.spiner.stopAnimation()
        self.isAnimating = false
    

    func cornerRadius() 
        let cornerRadiusAnim = CABasicAnimation(keyPath: "cornerRadius")
        // cornerRadiusAnim.fromValue = frame.width
        cornerRadiusAnim.toValue = frame.height/2
        cornerRadiusAnim.duration = shrinkDuration
        cornerRadiusAnim.timingFunction = shrinkCurve
        cornerRadiusAnim.fillMode = kCAFillModeForwards
        cornerRadiusAnim.isRemovedOnCompletion = false
        layer.add(cornerRadiusAnim, forKey: cornerRadiusAnim.keyPath)
    

    func shrink() 
        let shrinkAnim = CABasicAnimation(keyPath: "bounds.size.width")
        shrinkAnim.beginTime = CACurrentMediaTime() + 0.1
        shrinkAnim.fromValue = frame.width
        shrinkAnim.toValue = frame.height
        shrinkAnim.duration = shrinkDuration
        shrinkAnim.timingFunction = shrinkCurve
        shrinkAnim.fillMode = kCAFillModeForwards
        shrinkAnim.isRemovedOnCompletion = false
        layer.add(shrinkAnim, forKey: shrinkAnim.keyPath)
    

    func expand(_ animation: CAMediaTimingFunction) 
        let expandAnim = CABasicAnimation(keyPath: "transform.scale")
        expandAnim.fromValue = 1.0
        expandAnim.toValue = 26.0
        expandAnim.timingFunction = animation
        expandAnim.duration = 0.3
        expandAnim.delegate = self
        expandAnim.fillMode = kCAFillModeForwards
        expandAnim.isRemovedOnCompletion = false
        layer.add(expandAnim, forKey: expandAnim.keyPath)
    


【讨论】:

以上是关于Swift2:TKSubmitTransitionButton。当用户登录/注册不正确时,如何停止按钮的转换/动画的主要内容,如果未能解决你的问题,请参考以下文章

Swift2.0 Multipeer Connectivity 无法连接

NSFetchRequest 上的 Swift2.0 CoreData 问题

swift2.0中文版教程

Swift2 - HKSampleQuery

Swift2 - HKSampleQuery

swift2:调用中的额外参数“错误”