Display animated GIF in iOS
Objective CIosObjective C Problem Overview
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!
Objective C Solutions
Solution 1 - Objective C
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.
Solution 2 - Objective C
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:
Solution 3 - Objective C
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.
Solution 4 - Objective C
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.
Solution 5 - Objective C
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/
Solution 6 - Objective C
#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
Solution 7 - Objective C
Solution 8 - Objective C
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;
Solution 9 - Objective C
In 2021, splitting gif into individual frames is still a valid solution.
Here is the accepted answer adapted to Swift:
-
Split your gif into individual frames using an online service like ezygif: https://ezgif.com/split/ Make sure to export them as
.png
. -
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. -
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")
}
}