91

I noticed that with iMessage, animated gifs can now be sent and displayed. Does this mean that Apple is now supporting the display of animated GIFs in an application, or is the easiest method still to split the image in frames and then sequentially show them? What is the easiest way to display an animated GIF as of iOS 5.1?

Thanks!

swickblade
  • 4,506
  • 5
  • 21
  • 24

9 Answers9

144

If you are targeting iOS7 and already have the image split into frames you can use animatedImageNamed:duration:.

Let's say you are animating a spinner. Copy all of your frames into the project and name them as follows:

  • spinner-1.png
  • spinner-2.png
  • spinner-3.png
  • etc.,

Then create the image via:

[UIImage animatedImageNamed:@"spinner-" duration:1.0f];

From the docs:

This method loads a series of files by appending a series of numbers to the base file name provided in the name parameter. For example, if the name parameter had ‘image’ as its contents, this method would attempt to load images from files with the names ‘image0’, ‘image1’ and so on all the way up to ‘image1024’. All images included in the animated image should share the same size and scale.

Joe Masilotti
  • 16,815
  • 6
  • 77
  • 87
  • 6
    And if you don't have the animation in frames, you can open a GIF in the Preview app and just drag the frames out. The frames should be extracted as .tiff, so then see here: http://www.maclife.com/article/howtos/how_batch_convert_images_your_mac_without_photoshop – André Fratelli Sep 08 '14 at 02:18
38

I would recommend using the following code, it's much more lightweight, and compatible with ARC and non-ARC project, it adds a simple category on UIImageView:

https://github.com/mayoff/uiimage-from-animated-gif/

Eric
  • 16,003
  • 15
  • 87
  • 139
38

FLAnimatedImage is a performant open source animated GIF engine for iOS:

  • Plays multiple GIFs simultaneously with a playback speed comparable to desktop browsers
  • Honors variable frame delays
  • Behaves gracefully under memory pressure
  • Eliminates delays or blocking during the first playback loop
  • Interprets the frame delays of fast GIFs the same way modern browsers do

It's a well-tested component that I wrote to power all GIFs in Flipboard.

dandan78
  • 13,328
  • 13
  • 64
  • 78
Raphael Schaad
  • 1,659
  • 1
  • 17
  • 17
  • the current frame property is returning wrong fro this framework! https://github.com/Flipboard/FLAnimatedImage/issues/222 – Mo Farhand Mar 29 '20 at 08:08
13

Another alternative is to use a UIWebView to display the animated GIF. If the GIF is going to be fetched from a server, then this takes care of the fetching. It also works with local GIFs.

ThomasW
  • 16,981
  • 4
  • 79
  • 106
  • Thanks. This works good. However, there might be some lagging the first time gif is loaded into webview which causes the 'slow motion' of the animation. if u require it to be smoother, animating frames shared in the answer to this question might be better. – Hammer Sep 29 '15 at 09:09
  • 2
    "Starting in iOS 8.0 and OS X 10.10, use WKWebView to add web content to your app. Do not use UIWebView or WebView." https://developer.apple.com/reference/webkit/wkwebview – Jason Moore Jan 10 '17 at 14:31
  • 1
    Using WebKit to display a GIF is like buying a cargo ship to transport your groceries to your house. Web views are very very expensive and require the initialization of a full JavaScript and rendering engine. I’d highly recommend using an image view solution – Allison Mar 16 '19 at 19:18
8

From iOS 11 Photos framework allows to add animated Gifs playback.

Sample app can be dowloaded here

More info about animated Gifs playback (starting from 13:35 min): https://developer.apple.com/videos/play/wwdc2017/505/

enter image description here

sash
  • 8,423
  • 5
  • 63
  • 74
7
#import <QuickLook/QuickLook.h>
#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    QLPreviewController *preview = [[QLPreviewController alloc] init];
    preview.dataSource = self;

    [self addChildViewController:preview];
    [self.view addSubview:preview.view];
}

#pragma mark - QLPreviewControllerDataSource

- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)previewController
{
    return 1;
}

- (id)previewController:(QLPreviewController *)previewController previewItemAtIndex:(NSInteger)idx
{
    NSURL *fileURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"myanimated.gif" ofType:nil]];
    return fileURL;
}

@end
Erik Holley
  • 71
  • 1
  • 2
2

You can use SwiftGif from this link

Usage:

imageView.loadGif(name: "jeremy")
david72
  • 7,151
  • 3
  • 37
  • 59
1
NSString *pathForGif = [[NSBundle mainBundle] pathForResource:@"ic_homepage_random0330" ofType: @"gif"];

NSData *gifData = [NSData dataWithContentsOfFile:pathForGif];
                
YYImage *img = [YYImage imageWithData:gifData];

YYAnimatedImageView *contentImageView = [[YYAnimatedImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
contentImageView.autoPlayAnimatedImage = YES;
contentImageView.image = img;
Laurent
  • 12,287
  • 7
  • 21
  • 37
1

In 2021, splitting gif into individual frames is still a valid solution.

Here is the accepted answer adapted to Swift:

  1. Split your gif into individual frames using an online service like ezygif: https://ezgif.com/split/ Make sure to export them as .png.

  2. Create an xcassets arhcive and create an asset for each frame. Make sure that the difference is just the suffix which should be a number for each frame of the gif (i.e. animated-image-1, animaged-image-2, etc) I'm using a single scale to make it easier.

  3. Load it up into an image view:

final class AnimatedImage: UIImageView {
    init() {
        super.init(frame: .zero)

        let animatedImage = UIImage.animatedImageNamed("animated-image-", duration: 0.3)
        translatesAutoresizingMaskIntoConstraints = false
        image = animatedImage

        NSLayoutConstraint.activate([
            widthAnchor.constraint(equalToConstant: 150),
            heightAnchor.constraint(equalTo: widthAnchor)
        ])
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
Allan Spreys
  • 5,287
  • 5
  • 39
  • 44