fade between two UIButton images

You could try to transition the alpha values like this to get the effect that you want:

trans_img = [UIImage imageNamed:@"fav_on.png"];

NSArray *subviews = [owningCell subviews];
UIButton *favbutton = [subviews objectAtIndex:2];
[UIView animateWithDuration:0.5 animations:^{
    favbutton.alpha = 0.0f;
} completion:^(BOOL finished) {
    favbutton.imageView.animationImages = [NSArray arrayWithObjects:trans_img,nil];
    [favbutton.imageView startAnimating];
    [UIView animateWithDuration:0.5 animations:^{
        favbutton.alpha = 1.0f;
    }];
}];

Here in swift:

  import UIKit

   extension UIButton {

       func changeImageAnimated(image: UIImage?) {
           guard let imageView = self.imageView, currentImage = imageView.image, newImage = image else {
               return
           }
           let crossFade: CABasicAnimation = CABasicAnimation(keyPath: "contents")
           crossFade.duration = 0.3
           crossFade.fromValue = currentImage.CGImage
           crossFade.toValue = newImage.CGImage
           crossFade.removedOnCompletion = false
           crossFade.fillMode = kCAFillModeForwards
           imageView.layer.addAnimation(crossFade, forKey: "animateContents")
       }
   }


   self.playAndPauseVideo.changeImageAnimated(UIImage(named: "pauseVideo"))

Thank you to @jkanter for the great answer. I made mine into a Swift 3.0 extension that I thought might also be useful for anyone who stumbles upon this post.

extension UIButton {

    func setImage(_ image: UIImage?, for state: UIControlState, animated: Bool) {
        guard animated, let oldImage = imageView?.image, let newImage = image else {
            // Revert to default functionality
            setImage(image, for: state)
            return
        }

        let crossFade = CABasicAnimation(keyPath:"contents")
        crossFade.duration = 0.35
        crossFade.fromValue = oldImage.cgImage
        crossFade.toValue = newImage.cgImage
        crossFade.isRemovedOnCompletion = false
        imageView?.layer.add(crossFade, forKey: "animateContents")

        setImage(image, for: state)
    }
}

It seems like what you're looking for is this. It animates the images on a UIButton without adding new images, creating an array or changing alpha values!

CABasicAnimation *crossFade = [CABasicAnimation animationWithKeyPath:@"contents"];
crossFade.duration = 0.7;
crossFade.fromValue = (id)oldImage.CGImage;
crossFade.toValue = (id)newImage.CGImage;
crossFade.removedOnCompletion = NO;
crossFade.fillMode = kCAFillModeForwards;
[button.imageView.layer addAnimation:crossFade forKey:@"animateContents"];

//Make sure to add Image normally after so when the animation
//is done it is set to the new Image
[button setImage:newImage forState:UIControlStateNormal];