8

I am trying to display an animated gif in an overlay for MKMapView. The overlay is created using the MKOverlayRenderer. To animate the gif in iOS 7, I'm using the UIImage+animatedGIF category posted here on GitHub.

The image of the animated gif displays fine in the overlay using the category; however, the gif does not animate. I have no problem using the category to animate a gif in a UIImageView but it does not seem to work correctly in a map view overlay.

How can I use this category to place an animated gif in a map view overlay?

or...

Is there a way to place a UIImageView in the overlay which might solve my problem by setting the UIImageView with the animated gif?

My overlay renderer subclass is the following:

MapOverlayRenderer.h

#import <MapKit/MapKit.h>

@interface MapOverlayRenderer : MKOverlayRenderer
- (instancetype)initWithOverlay:(id<MKOverlay>)overlay overlayImage:(UIImage *)overlayImage;
@end

MapOverlayRenderer.m

#import "MapOverlayRenderer.h"

@interface MapOverlayRenderer ()
@property (strong,nonatomic) UIImage *image;
@end

@implementation MapOverlayRenderer

- (instancetype)initWithOverlay:(id<MKOverlay>)overlay overlayImage:(UIImage *)overlayImage {

    self = [super initWithOverlay:overlay];

    if (self) {
        _image = overlayImage;
    }

    return self;
}

- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context {

    CGImageRef imageReference = self.image.CGImage;

    MKMapRect theMapRect = [self.overlay boundingMapRect];
    CGRect theRect = [self rectForMapRect:theMapRect];

    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextTranslateCTM(context, 0.0, -theRect.size.height);

    CGContextDrawImage(context, theRect, imageReference);    
}

@end

In my UIViewController, I am fetching the animated gif and adding the overlay by calling a method which contains the following code:

NSURLSession *session = [NSURLSession sharedSession];

    [[session dataTaskWithURL:[NSURL URLWithString:radarUrl] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        self.radarImage = [UIImage animatedImageWithAnimatedGIFData:data];  //for animated radar image

        dispatch_async(dispatch_get_main_queue(), ^{

            [self.mapView addOverlay:self.polygon];

        });

    }] resume];

Any suggestions on how to animate a gif in an iOS 7 map view overlay would be greatly appreciated.

Shmidt
  • 16,436
  • 18
  • 88
  • 136
wigging
  • 8,492
  • 12
  • 75
  • 117
  • 1
    I have done something like that for rendering weather information on MapView Do you want like that only?If yes then let me know i will explain you in detail. – Ankit Vyas Dec 14 '13 at 09:58
  • @iosRider Yes, please explain in more detail or submit as an answer. – wigging Dec 14 '13 at 14:26

2 Answers2

3

https://github.com/jhurray/iOS7AnimatedMapOverlay

this is the best way to animate overlays in iOS7

jhurray
  • 81
  • 4
  • Link only answers are discouraged, can you summerize? – James Jenkins Jan 22 '14 at 19:39
  • Does this allow animated gifs to be displayed and animated in the overlay? – wigging Jan 23 '14 at 02:29
  • 1
    Sorry about that. What you have to do to properly animate over a map in iOS7 is add an animating view to your MKMapView. You can no longer add subviews to overlays. That also means that every time the mapViewRegionWill/DidChange you have to remove and add it to the appropriate spot. The appropriate calculations are in the linked github project above. – jhurray Feb 05 '14 at 01:30
1

Because a map view overlay is having your draw in a CGContext, it won't animate -- that is a buffer which is drawn to and translated to view contents, as opposed to being a normal part of the view hierarchy. Unfortunately you will need to make use of -setNeedsDisplayInMapRect:zoomScale: repeatedly to request animations. This system is a bit less flexible than iOS 6 and before, which added normal views atop the map.

incanus
  • 5,100
  • 1
  • 13
  • 20
  • So how do I use `setNeedsDisplayInMapRect` for the animated gif? – wigging Dec 14 '13 at 02:32
  • 1
    If if this way...I think you should probably setup a timer and call that 'setNeedsDisplayInMapRect' every interval? and ensure a new picture has been drawn in your 'drawMapRect' every time. – wdanxna Dec 16 '13 at 13:14
  • 1
    @wdanxna So are you saying to use the timer to display each frame of the gif? Could you submit an answer explaining this in more detail? – wigging Dec 16 '13 at 23:54
  • Yeah, this could get nasty, since you will need to calculate the current `MKMapRect` to cover the visible part of your image, but when you ask for the refresh with `setNeedsDisplayInMapRect:`, parts of it may load at different times. Depends on how fast your render routine is. – incanus Dec 19 '13 at 01:24
  • @incanus I'm thinking it may be better to place a `UIImageView` into the overlay (if that's possible). That way I know the `UIImage+animatedGIF` category should work since it's made for `UIImageView`. However, I have no idea at the moment how to programmatically place a UIImageView into the overlay renderer. Suggestions? – wigging Dec 19 '13 at 01:31
  • I don't think you're going to be able to do that with the new iOS 7 APIs. They are geared towards drawing static contents into a context as opposed to using a view hierarchy. – incanus Dec 31 '13 at 17:41
  • @incanus Well there is a bounty posted for this question. So if you can figure it out, then you'll get some extra points! – wigging Jan 04 '14 at 04:13