Search code examples
iosswiftanimationalamofirefacebook-pop

Animate UIView using pop animation while waiting Alamofire request finishes


I am trying to animate a custom button using Facebooks POP framework. The animation does not happen until the request is done using Alamofire.

What I want to do is make the request and during the waiting process animate the button.

The code below visually works, but it does the request after the animation finishes.

 func animate(tappedView:UIView){

    let rotation = POPBasicAnimation(propertyNamed: kPOPLayerRotationX)
    rotation.duration = 2.0
    rotation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    tappedView.layer.anchorPoint = CGPointMake(0.5, 0.5)
    rotation.toValue = 3*M_PI


    let scaleUp = POPBasicAnimation(propertyNamed: kPOPLayerSize)
    scaleUp.duration = 0.5
    scaleUp.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
    tappedView.layer.anchorPoint = CGPointMake(0.5, 0.5)
    let size = CGSizeMake(tappedView.frame.size.width ,tappedView.frame.size.height)
    let scaledSize = CGSizeMake(size.width * 1.5, size.height * 1.5)
    scaleUp.toValue = NSValue(CGSize: scaledSize)


    let scaleDown = POPSpringAnimation(propertyNamed: kPOPLayerSize)
    scaleDown.beginTime  = CACurrentMediaTime() + 0.5
    scaleDown.toValue = NSValue(CGSize: size)
    scaleDown.springSpeed = 4
    scaleDown.springBounciness = 8

    scaleDown.completionBlock = { (anim:POPAnimation!, finished:Bool) -> Void in

        let requestURL = self.prepare4SQrequest(withLocation: self.currentLocation)
        let request = Alamofire.request(.GET, requestURL)
        request.responseJSON{ response in
         HANDLE REQUEST RESPONSE LOGIC
    }


    tappedView.layer.pop_addAnimation(rotation, forKey: "popRotationX")
    tappedView.layer.pop_addAnimation(scaleUp, forKey: "popScaleUp")
    tappedView.layer.pop_addAnimation(scaleDown, forKey: "popScaleD")

}

I tried to make use of Alamofire's request.progress but it did not work. In this version the animation starts when the request logic finishes.

func animate(tappedView:UIView){

    let rotation = POPBasicAnimation(propertyNamed: kPOPLayerRotationX)
    rotation.duration = 2.0
    rotation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    tappedView.layer.anchorPoint = CGPointMake(0.5, 0.5)
    rotation.toValue = 3*M_PI


    let scaleUp = POPBasicAnimation(propertyNamed: kPOPLayerSize)
    scaleUp.duration = 0.5
    scaleUp.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
    tappedView.layer.anchorPoint = CGPointMake(0.5, 0.5)
    let size = CGSizeMake(tappedView.frame.size.width ,tappedView.frame.size.height)
    let scaledSize = CGSizeMake(size.width * 1.5, size.height * 1.5)
    scaleUp.toValue = NSValue(CGSize: scaledSize)


    let scaleDown = POPSpringAnimation(propertyNamed: kPOPLayerSize)
    scaleDown.beginTime  = CACurrentMediaTime() + 0.5
    scaleDown.toValue = NSValue(CGSize: size)
    scaleDown.springSpeed = 4
    scaleDown.springBounciness = 8


    tappedView.layer.pop_addAnimation(rotation, forKey: "popRotationX")
    tappedView.layer.pop_addAnimation(scaleUp, forKey: "popScaleUp")
    tappedView.layer.pop_addAnimation(scaleDown, forKey: "popScaleD")

}


func buttonTapped(gesture:UIGestureRecognizer){

    let tappedView:UIView = gesture.view!
    switch (tappedView.tag)
    {
    case 1:

        let requestURL = prepare4SQrequest(withLocation: currentLocation)
        let request = Alamofire.request(.GET, requestURL)
        request.progress({bytesRead, totalBytesRead, totalBytesExpectedToRead in
            dispatch_async(dispatch_get_main_queue()) {
                print("Total bytes to read : \(totalBytesExpectedToRead)")
                print("Total bytes read \(totalBytesRead)")
                print("Bytes read \(bytesRead)")
                self.animate(tappedView)
            }
        } )
        request.responseJSON{ response in

          HANDLE REQUEST RESPONSE LOGIC

        }

        break
      }

Any help would be appricieted.

Thank you


Solution

  • Your buttonTapped function should look like this

    func buttonTapped(gesture:UIGestureRecognizer) {
      // 1 do your setup and switch case
      // 2 first ask alamofire to send request
      Alamofire.request(.GET, requestURL).
      responseJSON {
        response in
        // handle response here
        stopAnimation()
      }
      // 3 call your animation
      animate(tappedView)
    }
    

    Now if you put a breakpoint on animate(tappedView) and code that handles json response you will see that your debugger will stop at animate first, then after a while will stop at response code. Alamofire has multithreading logic built in so you ask it to fetch you something from network and then it executes code you passed in the closure to .response whenever it's ready.

    Hope that helps!