├── .gitignore ├── AFNetworking ├── OLImageResponseSerializer.h ├── OLImageResponseSerializer.m ├── OLImageStrictResponseSerializer.h └── OLImageStrictResponseSerializer.m ├── Categories ├── AFImageRequestOperation+OLImage.h └── AFImageRequestOperation+OLImage.m ├── LICENSE ├── OLImage.h ├── OLImage.m ├── OLImageView.h ├── OLImageView.m ├── OLImageView.podspec ├── OLImageViewDelegate.h ├── OLImageViewDemo.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── OLImageViewDemo.xcworkspace └── contents.xcworkspacedata ├── OLImageViewDemo ├── Images │ ├── 1.gif │ ├── 10.gif │ ├── 2.gif │ ├── 3.gif │ ├── 4.gif │ ├── 5.gif │ ├── 6.gif │ ├── 7.gif │ ├── 8.gif │ ├── 9.gif │ ├── AA.gif │ ├── BB0.png │ ├── BB1.png │ ├── BB10.png │ ├── BB11.png │ ├── BB12.png │ ├── BB13.png │ ├── BB14.png │ ├── BB15.png │ ├── BB16.png │ ├── BB2.png │ ├── BB3.png │ ├── BB4.png │ ├── BB5.png │ ├── BB6.png │ ├── BB7.png │ ├── BB8.png │ ├── BB9.png │ ├── BLEH.gif │ ├── Default-568h@2x.png │ ├── fdgdf.gif │ ├── google-io.gif │ ├── google-io@2x.gif │ ├── google-io@3x.gif │ └── notEven.gif ├── OLAppDelegate.h ├── OLAppDelegate.m ├── OLImageViewDemo-Info.plist ├── OLImageViewDemo-Prefix.pch ├── en.lproj │ └── InfoPlist.strings └── main.m ├── Podfile ├── Podfile.lock └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | xcuserdata 4 | DerivedData 5 | Pods 6 | *.xccheckout 7 | -------------------------------------------------------------------------------- /AFNetworking/OLImageResponseSerializer.h: -------------------------------------------------------------------------------- 1 | // 2 | // OLImageResponseSerializer.h 3 | // OLImageViewDemo 4 | // 5 | // Created by Romans Karpelcevs on 29/05/14. 6 | // Copyright (c) 2014 Onda Labs. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface OLImageResponseSerializer : AFImageResponseSerializer 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /AFNetworking/OLImageResponseSerializer.m: -------------------------------------------------------------------------------- 1 | // 2 | // OLImageResponseSerializer.m 3 | // OLImageViewDemo 4 | // 5 | // Created by Romans Karpelcevs on 29/05/14. 6 | // Copyright (c) 2014 Onda Labs. All rights reserved. 7 | // 8 | 9 | #import "OLImageResponseSerializer.h" 10 | #import "OLImage.h" 11 | 12 | @implementation OLImageResponseSerializer 13 | 14 | - (id)responseObjectForResponse:(NSURLResponse *)response 15 | data:(NSData *)data 16 | error:(NSError *__autoreleasing *)error 17 | { 18 | return [OLImage imageWithData:data]; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /AFNetworking/OLImageStrictResponseSerializer.h: -------------------------------------------------------------------------------- 1 | // 2 | // OLImageStrictResponseSerializer.h 3 | // OLImageViewDemo 4 | // 5 | // Created by Romans Karpelcevs on 16/06/14. 6 | // Copyright (c) 2014 Onda Labs. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface OLImageStrictResponseSerializer : AFImageResponseSerializer 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /AFNetworking/OLImageStrictResponseSerializer.m: -------------------------------------------------------------------------------- 1 | // 2 | // OLImageStrictResponseSerializer.m 3 | // OLImageViewDemo 4 | // 5 | // Created by Romans Karpelcevs on 16/06/14. 6 | // Copyright (c) 2014 Onda Labs. All rights reserved. 7 | // 8 | 9 | #import "OLImageStrictResponseSerializer.h" 10 | #import "OLImage.h" 11 | 12 | @implementation OLImageStrictResponseSerializer 13 | 14 | - (id)init 15 | { 16 | self = [super init]; 17 | if (self) { 18 | self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"image/gif", nil]; 19 | } 20 | return self; 21 | } 22 | 23 | - (id)responseObjectForResponse:(NSURLResponse *)response 24 | data:(NSData *)data 25 | error:(NSError *__autoreleasing *)error 26 | { 27 | // Decode only valid response codes and MIME types 28 | if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) 29 | return nil; 30 | 31 | return [OLImage imageWithData:data]; 32 | } 33 | 34 | @end -------------------------------------------------------------------------------- /Categories/AFImageRequestOperation+OLImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // AFImageRequestOperation+OLImage.h 3 | // MMTmini 4 | // 5 | // Created by Diego Torres on 16-10-12. 6 | // Copyright (c) 2012 Onda. All rights reserved. 7 | // 8 | 9 | #import "AFImageRequestOperation.h" 10 | 11 | @interface AFImageRequestOperation (OLImage) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Categories/AFImageRequestOperation+OLImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // AFImageRequestOperation+OLImage.m 3 | // MMTmini 4 | // 5 | // Created by Diego Torres on 16-10-12. 6 | // Copyright (c) 2012 Onda. All rights reserved. 7 | // 8 | 9 | #import "AFImageRequestOperation+OLImage.h" 10 | #import 11 | #import "OLImage.h" 12 | 13 | @interface AFImageRequestOperation (privateAPI) 14 | 15 | - (void)setResponseImage:(UIImage *)image; 16 | 17 | @end 18 | 19 | @implementation AFImageRequestOperation (OLImage) 20 | 21 | - (void)setResponseOLImage:(UIImage *)responseImage { 22 | if ([self.responseData length] > 0 && [self isFinished]) { 23 | [self setResponseOLImage:[OLImage imageWithData:self.responseData scale:self.imageScale]]; 24 | } 25 | } 26 | 27 | + (void)load { 28 | method_exchangeImplementations(class_getInstanceMethod(self, @selector(setResponseImage:)), class_getInstanceMethod(self, @selector(setResponseOLImage:))); 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2012 Onda Labs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /OLImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // OLImage.h 3 | // MMT 4 | // 5 | // Created by Diego Torres on 9/1/12. 6 | // Copyright (c) 2012 Onda. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OLImage : UIImage 12 | 13 | ///----------------------- 14 | /// @name Image Attributes 15 | ///----------------------- 16 | 17 | /** 18 | A C array containing the frame durations. 19 | 20 | The number of frames is defined by the count of the `images` array property. 21 | */ 22 | @property (nonatomic, readonly) NSTimeInterval *frameDurations; 23 | 24 | /** 25 | Total duration of the animated image. 26 | */ 27 | @property (nonatomic, readonly) NSTimeInterval totalDuration; 28 | 29 | /** 30 | Number of loops the image can do before it stops 31 | */ 32 | @property (nonatomic, readonly) NSUInteger loopCount; 33 | 34 | @end 35 | 36 | 37 | ///---------------------------- 38 | /// @name Partial Image Methods 39 | ///---------------------------- 40 | 41 | @interface OLImage (IncrementalData) 42 | /** 43 | Creates and returns an image object with the Incremental Data processed 44 | 45 | @param data The image data. This can be partial data or `nil` 46 | @return A new image object with the specified data or partial container if none was provided. 47 | */ 48 | + (instancetype)imageWithIncrementalData:(NSData *)data; 49 | 50 | /** 51 | Update the image instance with new data 52 | 53 | @param data The image data. This can be partial data. 54 | This calls `updateWithData:final:` with `NO` as the `finalize` argument. 55 | */ 56 | - (void)updateWithData:(NSData *)data; 57 | 58 | /** 59 | Update the image instance with new data 60 | 61 | @param data The image data. This can be partial data. 62 | @param finalize `YES` if this the data provided is complete 63 | */ 64 | - (void)updateWithData:(NSData *)data final:(BOOL)finalize; 65 | 66 | /** 67 | Whether the instance is a partial or complete image. 68 | */ 69 | @property (nonatomic, readonly, getter = isPartial) BOOL partial; 70 | 71 | @end -------------------------------------------------------------------------------- /OLImage.m: -------------------------------------------------------------------------------- 1 | // 2 | // OLImage.m 3 | // MMT 4 | // 5 | // Created by Diego Torres on 9/1/12. 6 | // Copyright (c) 2012 Onda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "OLImage.h" 12 | 13 | //Define FLT_EPSILON because, reasons. 14 | //Actually, I don't know why but it seems under certain circumstances it is not defined 15 | #ifndef FLT_EPSILON 16 | #define FLT_EPSILON __FLT_EPSILON__ 17 | #endif 18 | 19 | inline static NSTimeInterval CGImageSourceGetGifFrameDelay(CGImageSourceRef imageSource, NSUInteger index) 20 | { 21 | NSTimeInterval frameDuration = 0; 22 | CFDictionaryRef theImageProperties; 23 | if ((theImageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, index, NULL))) { 24 | CFDictionaryRef gifProperties; 25 | if (CFDictionaryGetValueIfPresent(theImageProperties, kCGImagePropertyGIFDictionary, (const void **)&gifProperties)) { 26 | const void *frameDurationValue; 27 | if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFUnclampedDelayTime, &frameDurationValue)) { 28 | frameDuration = [(__bridge NSNumber *)frameDurationValue doubleValue]; 29 | if (frameDuration <= 0) { 30 | if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFDelayTime, &frameDurationValue)) { 31 | frameDuration = [(__bridge NSNumber *)frameDurationValue doubleValue]; 32 | } 33 | } 34 | } 35 | } 36 | CFRelease(theImageProperties); 37 | } 38 | 39 | #ifndef OLExactGIFRepresentation 40 | //Implement as Browsers do. 41 | //See: http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser-compatibility 42 | //Also: http://blogs.msdn.com/b/ieinternals/archive/2010/06/08/animated-gifs-slow-down-to-under-20-frames-per-second.aspx 43 | 44 | if (frameDuration < 0.02 - FLT_EPSILON) { 45 | frameDuration = 0.1; 46 | } 47 | #endif 48 | return frameDuration; 49 | } 50 | 51 | inline static BOOL CGImageSourceContainsAnimatedGif(CGImageSourceRef imageSource) 52 | { 53 | return imageSource && UTTypeConformsTo(CGImageSourceGetType(imageSource), kUTTypeGIF) && CGImageSourceGetCount(imageSource) > 1; 54 | } 55 | 56 | inline static BOOL isRetinaFilePath(NSString *path) 57 | { 58 | NSRange retinaSuffixRange = [[path lastPathComponent] rangeOfString:@"@2x" options:NSCaseInsensitiveSearch]; 59 | return retinaSuffixRange.length && retinaSuffixRange.location != NSNotFound; 60 | } 61 | 62 | @interface OLImageSourceArray : NSArray 63 | 64 | @property (nonatomic, readonly) CGImageSourceRef imageSource; 65 | 66 | - (void)updateCount; 67 | 68 | + (instancetype)arrayWithImageSource:(CGImageSourceRef)imageSource; 69 | + (instancetype)arrayWithImageSource:(CGImageSourceRef)imageSource scale:(CGFloat)scale; 70 | 71 | @end 72 | 73 | @interface OLImage () 74 | 75 | @property (nonatomic, readwrite) NSTimeInterval *frameDurations; 76 | @property (nonatomic, readwrite) NSTimeInterval totalDuration; 77 | @property (nonatomic, readwrite) NSUInteger loopCount; 78 | @property (nonatomic, readwrite) CGImageSourceRef incrementalSource; 79 | @property (nonatomic, readwrite) OLImageSourceArray *imageSourceArray; 80 | 81 | @end 82 | 83 | @implementation OLImage 84 | 85 | @synthesize images; 86 | 87 | #pragma mark - Class Methods 88 | 89 | + (id)imageNamed:(NSString *)name 90 | { 91 | NSString *requestedExtension = [name pathExtension]; 92 | if (requestedExtension) { 93 | name = [name substringWithRange:NSMakeRange(0, name.length-(requestedExtension.length+1))];//ext + dot 94 | } 95 | 96 | NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"lastPathComponent contains[cd] %@", name]; 97 | 98 | NSURL *bundleURL = [[NSBundle mainBundle] bundleURL]; 99 | NSArray *paths = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:bundleURL includingPropertiesForKeys:[NSArray array] options:0 error:NULL]; 100 | NSArray *namedPaths = [paths filteredArrayUsingPredicate:namePredicate]; 101 | 102 | if (namedPaths.count > 1) { 103 | NSString *extension = requestedExtension ? : @"gif"; 104 | NSPredicate *extPredicate = [NSPredicate predicateWithFormat:@"pathExtension contains[cd] %@", extension]; 105 | NSArray *extPaths = [namedPaths filteredArrayUsingPredicate:extPredicate]; 106 | if (extPaths.count > 0) { 107 | namedPaths = extPaths; 108 | } 109 | } 110 | 111 | NSURL *fileURL = nil; 112 | CGFloat fileURLScale = -1; 113 | if (namedPaths.count > 1) { 114 | CGFloat targetScale = [UIScreen mainScreen].scale; 115 | 116 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 117 | if ([[UIScreen mainScreen] respondsToSelector:@selector(nativeScale)]) { 118 | targetScale = [UIScreen mainScreen].nativeScale; //This property returns @3x 119 | } 120 | #endif 121 | 122 | NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"@([0-9]+)x\\." options:NSRegularExpressionCaseInsensitive error:NULL]; 123 | 124 | for (NSURL *aFileURL in namedPaths.reverseObjectEnumerator) { 125 | NSString *filename = [aFileURL lastPathComponent]; 126 | NSTextCheckingResult *result = [regex firstMatchInString:filename options:0 range:NSMakeRange(0, filename.length)]; 127 | if (result.numberOfRanges > 1) { 128 | CGFloat foundScale = [[filename substringWithRange:[result rangeAtIndex:1]] floatValue]; 129 | if (foundScale > fileURLScale && foundScale <= targetScale) { 130 | fileURLScale = foundScale; 131 | fileURL = aFileURL; 132 | } 133 | 134 | if (foundScale == targetScale) { 135 | break; 136 | } 137 | } 138 | } 139 | 140 | if (fileURL == nil) { 141 | fileURL = [namedPaths lastObject]; 142 | } 143 | } else if (namedPaths.count == 1) { 144 | fileURL = namedPaths.lastObject; 145 | } 146 | 147 | if (fileURLScale < 0) { 148 | fileURLScale = 1; 149 | } 150 | 151 | return [self imageWithData:[NSData dataWithContentsOfURL:fileURL] 152 | scale:fileURLScale]; 153 | } 154 | 155 | + (id)imageWithContentsOfFile:(NSString *)path 156 | { 157 | return [self imageWithData:[NSData dataWithContentsOfFile:path] 158 | scale:isRetinaFilePath(path) ? 2.0f : 1.0f]; 159 | } 160 | 161 | + (id)imageWithData:(NSData *)data 162 | { 163 | return [self imageWithData:data scale:1.0f]; 164 | } 165 | 166 | + (id)imageWithData:(NSData *)data scale:(CGFloat)scale 167 | { 168 | if (!data) { 169 | return nil; 170 | } 171 | 172 | CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)(data), NULL); 173 | UIImage *image; 174 | 175 | if (CGImageSourceContainsAnimatedGif(imageSource)) { 176 | image = [[self alloc] initWithCGImageSource:imageSource scale:scale]; 177 | } else { 178 | image = [super imageWithData:data scale:scale]; 179 | } 180 | 181 | if (imageSource) { 182 | CFRelease(imageSource); 183 | } 184 | 185 | return image; 186 | } 187 | 188 | #pragma mark - Initialization methods 189 | 190 | - (id)initWithContentsOfFile:(NSString *)path 191 | { 192 | return [self initWithData:[NSData dataWithContentsOfFile:path] 193 | scale:isRetinaFilePath(path) ? 2.0f : 1.0f]; 194 | } 195 | 196 | - (id)initWithData:(NSData *)data 197 | { 198 | return [self initWithData:data scale:1.0f]; 199 | } 200 | 201 | - (id)initWithData:(NSData *)data scale:(CGFloat)scale 202 | { 203 | if (!data) { 204 | return nil; 205 | } 206 | 207 | CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)(data), NULL); 208 | 209 | if (CGImageSourceContainsAnimatedGif(imageSource)) { 210 | self = [self initWithCGImageSource:imageSource scale:scale]; 211 | } else { 212 | if (scale == 1.0f) { 213 | self = [super initWithData:data]; 214 | } else { 215 | self = [super initWithData:data scale:scale]; 216 | } 217 | } 218 | 219 | if (imageSource) { 220 | CFRelease(imageSource); 221 | } 222 | 223 | return self; 224 | } 225 | 226 | - (id)initWithCGImageSource:(CGImageSourceRef)imageSource scale:(CGFloat)scale 227 | { 228 | self = [super init]; 229 | if (!imageSource || !self) { 230 | return nil; 231 | } 232 | 233 | NSUInteger numberOfFrames = CGImageSourceGetCount(imageSource); 234 | 235 | NSDictionary *imageProperties = CFBridgingRelease(CGImageSourceCopyProperties(imageSource, NULL)); 236 | NSDictionary *gifProperties = [imageProperties objectForKey:(NSString *)kCGImagePropertyGIFDictionary]; 237 | 238 | self.frameDurations = (NSTimeInterval *)malloc(numberOfFrames * sizeof(NSTimeInterval)); 239 | self.loopCount = [gifProperties[(NSString *)kCGImagePropertyGIFLoopCount] unsignedIntegerValue]; 240 | for (NSUInteger i = 0; i < numberOfFrames; ++i) { 241 | NSTimeInterval frameDuration = CGImageSourceGetGifFrameDelay(imageSource, i); 242 | self.frameDurations[i] = frameDuration; 243 | self.totalDuration += frameDuration; 244 | } 245 | self.imageSourceArray = [OLImageSourceArray arrayWithImageSource:imageSource scale:scale]; 246 | 247 | return self; 248 | } 249 | 250 | #pragma mark - Compatibility methods 251 | 252 | - (NSArray *)images 253 | { 254 | return self.imageSourceArray; 255 | } 256 | 257 | - (CGSize)size 258 | { 259 | if (self.images.count) { 260 | return [(UIImage *)self.images.firstObject size]; 261 | } 262 | return [super size]; 263 | } 264 | 265 | - (CGImageRef)CGImage 266 | { 267 | if (self.images.count) { 268 | return [(UIImage *)self.images.firstObject CGImage]; 269 | } else { 270 | return [super CGImage]; 271 | } 272 | } 273 | 274 | - (UIImageOrientation)imageOrientation 275 | { 276 | if (self.images.count) { 277 | return [(UIImage *)self.images.firstObject imageOrientation]; 278 | } else { 279 | return [super imageOrientation]; 280 | } 281 | } 282 | 283 | - (CGFloat)scale 284 | { 285 | if (self.images.count) { 286 | return [(UIImage *)self.images.firstObject scale]; 287 | } else { 288 | return [super scale]; 289 | } 290 | } 291 | 292 | - (NSTimeInterval)duration 293 | { 294 | return self.images ? self.totalDuration : [super duration]; 295 | } 296 | 297 | - (void)dealloc { 298 | free(_frameDurations); 299 | } 300 | 301 | @end 302 | 303 | @implementation OLImage (IncrementalData) 304 | 305 | + (instancetype)imageWithIncrementalData:(NSData *)data 306 | { 307 | OLImage *image = [[OLImage alloc] init]; 308 | image.totalDuration = 0; 309 | CGImageSourceRef incrementalSource = CGImageSourceCreateIncremental(NULL); 310 | image.imageSourceArray = [OLImageSourceArray arrayWithImageSource:incrementalSource]; 311 | image.incrementalSource = incrementalSource; 312 | image.totalDuration = 0; 313 | image.frameDurations = calloc(1, sizeof(NSTimeInterval)); 314 | 315 | CFRelease(incrementalSource); 316 | if (data) { 317 | [image updateWithData:data]; 318 | } 319 | return image; 320 | } 321 | 322 | - (void)updateWithData:(NSData *)data 323 | { 324 | [self updateWithData:data final:NO]; 325 | } 326 | 327 | - (void)updateWithData:(NSData *)data final:(BOOL)final 328 | { 329 | if (![self isPartial]) { 330 | return; 331 | } 332 | 333 | 334 | CGImageSourceUpdateData(_incrementalSource, (__bridge CFDataRef)([data copy]), final); 335 | [self.imageSourceArray updateCount]; 336 | [self updateDurations]; 337 | 338 | if (final) { 339 | _incrementalSource = NULL; 340 | } 341 | } 342 | 343 | - (void)updateDurations 344 | { 345 | NSUInteger count = self.imageSourceArray.count; 346 | NSTimeInterval totalDuration = 0; 347 | NSTimeInterval *durations = calloc(count, sizeof(NSTimeInterval)); 348 | for (int i = 0; i < count; i++) { 349 | NSTimeInterval delay = CGImageSourceGetGifFrameDelay(_incrementalSource, i); 350 | durations[i] = delay; 351 | totalDuration += delay; 352 | } 353 | 354 | free(_frameDurations); 355 | _frameDurations = durations; 356 | self.totalDuration = totalDuration; 357 | } 358 | 359 | - (BOOL)isPartial 360 | { 361 | return _incrementalSource != nil; 362 | } 363 | 364 | @end 365 | 366 | @interface OLImageSourceArray () 367 | 368 | @property (nonatomic, readonly) NSCache *frameCache; 369 | @property (nonatomic) NSUInteger frameCount; 370 | @property (nonatomic, readonly) CGFloat scale; 371 | 372 | @end 373 | 374 | @implementation OLImageSourceArray 375 | 376 | + (instancetype)arrayWithImageSource:(CGImageSourceRef)imageSource 377 | { 378 | return [self arrayWithImageSource:imageSource scale:1.0f]; 379 | } 380 | 381 | + (instancetype)arrayWithImageSource:(CGImageSourceRef)imageSource scale:(CGFloat)scale 382 | { 383 | if (!imageSource) { 384 | return nil; 385 | } 386 | return [[self alloc] initWithImageSource:imageSource scale:scale]; 387 | } 388 | 389 | - (instancetype)initWithImageSource:(CGImageSourceRef)imageSource scale:(CGFloat)scale 390 | { 391 | self = [super init]; 392 | if (self) { 393 | CFRetain(imageSource); 394 | _imageSource = imageSource; 395 | _frameCache = [NSCache new]; 396 | [_frameCache setCountLimit:10]; 397 | _frameCount = 0; 398 | _scale = scale; 399 | [self updateCount]; 400 | } 401 | return self; 402 | } 403 | 404 | - (NSUInteger)count 405 | { 406 | return self.frameCount; 407 | } 408 | 409 | - (id)objectAtIndex:(NSUInteger)idx 410 | { 411 | id object = [self.frameCache objectForKey:@(idx)]; 412 | if (!object) { 413 | object = [self _objectAtIndex:idx]; 414 | } 415 | return object; 416 | } 417 | 418 | - (BOOL)containsObject:(id)anObject 419 | { 420 | return [[(id)self.frameCache allObjects] containsObject:anObject]; 421 | } 422 | 423 | - (id)_objectAtIndex:(NSUInteger)idx 424 | { 425 | CGImageRef frameImageRef = CGImageSourceCreateImageAtIndex(self.imageSource, idx, NULL); 426 | UIImage *image = [UIImage imageWithCGImage:frameImageRef scale:self.scale orientation:UIImageOrientationUp]; 427 | CGImageRelease(frameImageRef); 428 | if (image) { 429 | [self.frameCache setObject:image forKey:@(idx)]; 430 | } 431 | return image; 432 | } 433 | 434 | - (void)updateCount 435 | { 436 | NSInteger count = CGImageSourceGetCount(self.imageSource); 437 | if (CGImageSourceGetStatus(self.imageSource) != kCGImageStatusComplete) { 438 | count -=2; 439 | } 440 | self.frameCount = MAX(0, count); 441 | NSUInteger cacheLimit = self.frameCache.countLimit; 442 | if (self.frameCount > 0) { 443 | cacheLimit = MIN(self.frameCount, 10); 444 | } 445 | [self.frameCache setCountLimit:cacheLimit]; 446 | } 447 | 448 | - (void)dealloc 449 | { 450 | CFRelease(_imageSource); 451 | } 452 | 453 | @end 454 | -------------------------------------------------------------------------------- /OLImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // OLImageView.h 3 | // OLImageViewDemo 4 | // 5 | // Created by Diego Torres on 9/5/12. 6 | // Copyright (c) 2012 Onda Labs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "OLImageViewDelegate.h" 12 | 13 | @interface OLImageView : UIImageView 14 | 15 | /** 16 | The animation runloop mode. 17 | 18 | The default mode (NSDefaultRunLoopMode), causes the animation to pauses while it is contained in an actively scrolling `UIScrollView`. Use NSRunLoopCommonModes if you don't want this behavior. 19 | */ 20 | @property (nonatomic, copy) NSString *runLoopMode; 21 | 22 | @property (nonatomic, weak) id delegate; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /OLImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // OLImageView.m 3 | // OLImageViewDemo 4 | // 5 | // Created by Diego Torres on 9/5/12. 6 | // Copyright (c) 2012 Onda Labs. All rights reserved. 7 | // 8 | 9 | #import "OLImageView.h" 10 | #import "OLImage.h" 11 | #import 12 | 13 | @interface OLImageView () { 14 | struct { 15 | unsigned int didLoop : 1; 16 | unsigned int shouldStartAnimating : 1; 17 | } _delegateFlags; 18 | } 19 | 20 | @property (nonatomic, strong) OLImage *animatedImage; 21 | @property (nonatomic, strong) CADisplayLink *displayLink; 22 | @property (nonatomic) NSTimeInterval accumulator; 23 | @property (nonatomic) NSUInteger currentFrameIndex; 24 | @property (nonatomic) NSUInteger loopCountdown; 25 | 26 | @end 27 | 28 | @implementation OLImageView 29 | 30 | const NSTimeInterval kMaxTimeStep = 1; // note: To avoid spiral-o-death 31 | 32 | @synthesize runLoopMode = _runLoopMode; 33 | @synthesize displayLink = _displayLink; 34 | 35 | - (id)init 36 | { 37 | self = [super init]; 38 | if (self) { 39 | self.currentFrameIndex = 0; 40 | } 41 | return self; 42 | } 43 | 44 | - (CADisplayLink *)displayLink 45 | { 46 | if (self.superview) { 47 | if (!_displayLink && self.animatedImage && [self delegateShouldStartAnimating]) { 48 | _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(changeKeyframe:)]; 49 | [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:self.runLoopMode]; 50 | } 51 | } else { 52 | [_displayLink invalidate]; 53 | _displayLink = nil; 54 | } 55 | return _displayLink; 56 | } 57 | 58 | - (NSString *)runLoopMode 59 | { 60 | return _runLoopMode ?: NSDefaultRunLoopMode; 61 | } 62 | 63 | - (void)setRunLoopMode:(NSString *)runLoopMode 64 | { 65 | if (runLoopMode != _runLoopMode) { 66 | [self stopAnimating]; 67 | 68 | NSRunLoop *runloop = [NSRunLoop mainRunLoop]; 69 | [self.displayLink removeFromRunLoop:runloop forMode:_runLoopMode]; 70 | [self.displayLink addToRunLoop:runloop forMode:runLoopMode]; 71 | 72 | _runLoopMode = runLoopMode; 73 | 74 | [self startAnimating]; 75 | } 76 | } 77 | 78 | - (void)setDelegate:(id)delegate 79 | { 80 | if (delegate == _delegate) { 81 | return; 82 | } 83 | _delegate = delegate; 84 | _delegateFlags.didLoop = [delegate respondsToSelector:@selector(imageViewDidLoop:)]; 85 | _delegateFlags.shouldStartAnimating = [delegate respondsToSelector:@selector(imageViewShouldStartAnimating:)]; 86 | } 87 | 88 | - (void)setImage:(UIImage *)image 89 | { 90 | if (image == self.image) { 91 | return; 92 | } 93 | 94 | [self stopAnimating]; 95 | 96 | self.currentFrameIndex = 0; 97 | self.loopCountdown = 0; 98 | self.accumulator = 0; 99 | 100 | if ([image isKindOfClass:[OLImage class]] && image.images) { 101 | [super setImage:nil]; 102 | self.animatedImage = (OLImage *)image; 103 | self.loopCountdown = self.animatedImage.loopCount ?: NSUIntegerMax; 104 | [self startAnimating]; 105 | } else { 106 | self.animatedImage = nil; 107 | [super setImage:image]; 108 | } 109 | [self.layer setNeedsDisplay]; 110 | } 111 | 112 | - (void)setAnimatedImage:(OLImage *)animatedImage 113 | { 114 | _animatedImage = animatedImage; 115 | if (animatedImage == nil) { 116 | self.layer.contents = nil; 117 | self.layer.contentsScale = 1; 118 | } else { 119 | self.layer.contentsScale = animatedImage.scale; 120 | } 121 | } 122 | 123 | #define OLCaseContentMode(aCase) \ 124 | case UIViewContentMode##aCase: \ 125 | contentsGravity = kCAGravity##aCase; \ 126 | break 127 | 128 | - (void)setContentMode:(UIViewContentMode)contentMode 129 | { 130 | NSString *contentsGravity; 131 | switch (contentMode) { 132 | OLCaseContentMode(Bottom); 133 | OLCaseContentMode(BottomLeft); 134 | OLCaseContentMode(BottomRight); 135 | OLCaseContentMode(Top); 136 | OLCaseContentMode(TopLeft); 137 | OLCaseContentMode(TopRight); 138 | OLCaseContentMode(Center); 139 | OLCaseContentMode(Right); 140 | OLCaseContentMode(Left); 141 | case UIViewContentModeScaleAspectFill: 142 | contentsGravity = kCAGravityResizeAspectFill; 143 | break; 144 | case UIViewContentModeScaleAspectFit: 145 | contentsGravity = kCAGravityResizeAspect; 146 | break; 147 | case UIViewContentModeScaleToFill: 148 | case UIViewContentModeRedraw: 149 | contentsGravity = kCAGravityResize; 150 | break; 151 | } 152 | self.layer.contentsGravity = contentsGravity; 153 | [super setContentMode:contentMode]; 154 | } 155 | 156 | - (BOOL)isAnimating 157 | { 158 | return [super isAnimating] || (self.displayLink && !self.displayLink.isPaused); 159 | } 160 | 161 | - (void)stopAnimating 162 | { 163 | if (!self.animatedImage) { 164 | [super stopAnimating]; 165 | return; 166 | } 167 | 168 | self.loopCountdown = 0; 169 | 170 | self.displayLink.paused = YES; 171 | } 172 | 173 | - (void)startAnimating 174 | { 175 | if (!self.animatedImage) { 176 | [super startAnimating]; 177 | return; 178 | } 179 | 180 | if (self.isAnimating) { 181 | return; 182 | } 183 | 184 | self.loopCountdown = self.animatedImage.loopCount ?: NSUIntegerMax; 185 | 186 | self.displayLink.paused = ! [self delegateShouldStartAnimating]; 187 | } 188 | 189 | - (void)changeKeyframe:(CADisplayLink *)displayLink 190 | { 191 | if (self.currentFrameIndex >= [self.animatedImage.images count] && [self.animatedImage isPartial]) { 192 | return; 193 | } 194 | self.accumulator += fmin(displayLink.duration, kMaxTimeStep); 195 | 196 | while (self.accumulator >= self.animatedImage.frameDurations[self.currentFrameIndex]) { 197 | self.accumulator -= self.animatedImage.frameDurations[self.currentFrameIndex]; 198 | if (++self.currentFrameIndex >= [self.animatedImage.images count] && ![self.animatedImage isPartial]) { 199 | if (--self.loopCountdown == 0) { 200 | [self stopAnimating]; 201 | return; 202 | } 203 | self.currentFrameIndex = 0; 204 | [self delegateDidLoop]; 205 | } 206 | self.currentFrameIndex = MIN(self.currentFrameIndex, [self.animatedImage.images count] - 1); 207 | [self.layer setNeedsDisplay]; 208 | } 209 | } 210 | 211 | - (void)displayLayer:(CALayer *)layer 212 | { 213 | if (!self.animatedImage || [self.animatedImage.images count] == 0) { 214 | return; 215 | } 216 | layer.contents = (__bridge id)([[self.animatedImage.images objectAtIndex:self.currentFrameIndex] CGImage]); 217 | } 218 | 219 | - (void)didMoveToWindow 220 | { 221 | [super didMoveToWindow]; 222 | if (self.window) { 223 | [self startAnimating]; 224 | } else { 225 | dispatch_async(dispatch_get_main_queue(), ^{ 226 | if (!self.window) { 227 | [self stopAnimating]; 228 | } 229 | }); 230 | } 231 | } 232 | 233 | - (void)didMoveToSuperview 234 | { 235 | [super didMoveToSuperview]; 236 | if (self.superview) { 237 | //Has a superview, make sure it has a displayLink 238 | [self displayLink]; 239 | } else { 240 | //Doesn't have superview, let's check later if we need to remove the displayLink 241 | dispatch_async(dispatch_get_main_queue(), ^{ 242 | [self displayLink]; 243 | }); 244 | } 245 | } 246 | 247 | - (void)setHighlighted:(BOOL)highlighted 248 | { 249 | if (!self.animatedImage) { 250 | [super setHighlighted:highlighted]; 251 | } 252 | } 253 | 254 | - (UIImage *)image 255 | { 256 | return self.animatedImage ?: [super image]; 257 | } 258 | 259 | - (CGSize)sizeThatFits:(CGSize)size 260 | { 261 | return self.image.size; 262 | } 263 | 264 | #pragma mark - delegation 265 | - (BOOL)delegateShouldStartAnimating { 266 | 267 | if (self.delegate && _delegateFlags.shouldStartAnimating) { 268 | return [self.delegate imageViewShouldStartAnimating:self]; 269 | } else { 270 | return YES; 271 | } 272 | } 273 | 274 | - (void)delegateDidLoop { 275 | 276 | if (self.delegate && _delegateFlags.didLoop) { 277 | [self.delegate imageViewDidLoop:self]; 278 | } 279 | } 280 | @end 281 | -------------------------------------------------------------------------------- /OLImageView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "OLImageView" 3 | s.version = "1.5" 4 | s.summary = "Animated GIFs implemented the right way." 5 | s.homepage = "https://www.github.com/ondalabs/OLImageView" 6 | s.license = { :type => 'MIT', :file => 'LICENSE' } 7 | s.author = { "Diego Torres" => "contact@dtorres.me" } 8 | s.source = { :git => "https://github.com/ondalabs/OLImageView.git", :tag => s.version.to_s } 9 | s.platform = :ios, '5.0' 10 | s.framework = 'ImageIO', 'MobileCoreServices', 'QuartzCore' 11 | s.requires_arc = true 12 | s.default_subspec = 'Core' 13 | 14 | s.subspec 'Core' do |core| 15 | core.source_files = 'OLImage.{h,m}', 'OLImageView.{h,m}', 'OLImageViewDelegate.h' 16 | end 17 | 18 | s.subspec 'AFNetworking' do |af| 19 | af.dependency 'OLImageView/Core' 20 | af.dependency 'AFNetworking', '~> 1.0' 21 | af.source_files = "Categories/AFImageRequestOperation+OLImage.{h,m}" 22 | end 23 | 24 | s.subspec 'AFNetworking2' do |ss| 25 | s.platform = :ios, '6.0' 26 | ss.dependency 'OLImageView/Core' 27 | ss.dependency 'AFNetworking', '~> 2.0' 28 | ss.source_files = "AFNetworking/OL*.{h,m}" 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /OLImageViewDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // OLImageViewDelegate.h 3 | // OLImageViewDemo 4 | // 5 | // Created by Rich Schonthal on 4/16/15. 6 | // Copyright (c) 2015 Onda Labs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class OLImageView; 12 | 13 | @protocol OLImageViewDelegate 14 | 15 | @optional 16 | 17 | - (BOOL)imageViewShouldStartAnimating:(OLImageView *)imageView; 18 | 19 | - (void)imageViewDidLoop:(OLImageView *)imageView; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /OLImageViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 07BB9C5F170696E800E68171 /* 1.gif in Resources */ = {isa = PBXBuildFile; fileRef = 07BB9C55170696E800E68171 /* 1.gif */; }; 11 | 07BB9C60170696E800E68171 /* 2.gif in Resources */ = {isa = PBXBuildFile; fileRef = 07BB9C56170696E800E68171 /* 2.gif */; }; 12 | 07BB9C61170696E800E68171 /* 3.gif in Resources */ = {isa = PBXBuildFile; fileRef = 07BB9C57170696E800E68171 /* 3.gif */; }; 13 | 07BB9C62170696E800E68171 /* 4.gif in Resources */ = {isa = PBXBuildFile; fileRef = 07BB9C58170696E800E68171 /* 4.gif */; }; 14 | 07BB9C63170696E800E68171 /* 5.gif in Resources */ = {isa = PBXBuildFile; fileRef = 07BB9C59170696E800E68171 /* 5.gif */; }; 15 | 07BB9C64170696E800E68171 /* 6.gif in Resources */ = {isa = PBXBuildFile; fileRef = 07BB9C5A170696E800E68171 /* 6.gif */; }; 16 | 07BB9C65170696E800E68171 /* 7.gif in Resources */ = {isa = PBXBuildFile; fileRef = 07BB9C5B170696E800E68171 /* 7.gif */; }; 17 | 07BB9C66170696E800E68171 /* 8.gif in Resources */ = {isa = PBXBuildFile; fileRef = 07BB9C5C170696E800E68171 /* 8.gif */; }; 18 | 07BB9C67170696E800E68171 /* 9.gif in Resources */ = {isa = PBXBuildFile; fileRef = 07BB9C5D170696E800E68171 /* 9.gif */; }; 19 | 07BB9C68170696E800E68171 /* 10.gif in Resources */ = {isa = PBXBuildFile; fileRef = 07BB9C5E170696E800E68171 /* 10.gif */; }; 20 | 5A053BE215F844060014BF82 /* BLEH.gif in Resources */ = {isa = PBXBuildFile; fileRef = 5A053BE115F844060014BF82 /* BLEH.gif */; }; 21 | 5A1F4BBD165C449E00B61FCF /* OLImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A1F4BBA165C449E00B61FCF /* OLImage.m */; }; 22 | 5A1F4BBE165C449E00B61FCF /* OLImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A1F4BBC165C449E00B61FCF /* OLImageView.m */; }; 23 | 5A2FFAA415F7F56100CEE5F6 /* notEven.gif in Resources */ = {isa = PBXBuildFile; fileRef = 5A2FFAA315F7F56100CEE5F6 /* notEven.gif */; }; 24 | 5A2FFAA715F800D500CEE5F6 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A2FFAA615F800D500CEE5F6 /* QuartzCore.framework */; }; 25 | 5A796D0215F79EC7008A8FBF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A796D0115F79EC7008A8FBF /* UIKit.framework */; }; 26 | 5A796D0415F79EC7008A8FBF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A796D0315F79EC7008A8FBF /* Foundation.framework */; }; 27 | 5A796D0615F79EC7008A8FBF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A796D0515F79EC7008A8FBF /* CoreGraphics.framework */; }; 28 | 5A796D0C15F79EC7008A8FBF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D0A15F79EC7008A8FBF /* InfoPlist.strings */; }; 29 | 5A796D0E15F79EC8008A8FBF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A796D0D15F79EC8008A8FBF /* main.m */; }; 30 | 5A796D1215F79EC8008A8FBF /* OLAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A796D1115F79EC8008A8FBF /* OLAppDelegate.m */; }; 31 | 5A796D3515F7ABD9008A8FBF /* BB1.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D2515F7ABD9008A8FBF /* BB1.png */; }; 32 | 5A796D3615F7ABD9008A8FBF /* BB2.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D2615F7ABD9008A8FBF /* BB2.png */; }; 33 | 5A796D3715F7ABD9008A8FBF /* BB3.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D2715F7ABD9008A8FBF /* BB3.png */; }; 34 | 5A796D3815F7ABD9008A8FBF /* BB4.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D2815F7ABD9008A8FBF /* BB4.png */; }; 35 | 5A796D3915F7ABD9008A8FBF /* BB5.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D2915F7ABD9008A8FBF /* BB5.png */; }; 36 | 5A796D3A15F7ABD9008A8FBF /* BB6.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D2A15F7ABD9008A8FBF /* BB6.png */; }; 37 | 5A796D3B15F7ABD9008A8FBF /* BB7.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D2B15F7ABD9008A8FBF /* BB7.png */; }; 38 | 5A796D3C15F7ABD9008A8FBF /* BB8.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D2C15F7ABD9008A8FBF /* BB8.png */; }; 39 | 5A796D3D15F7ABD9008A8FBF /* BB9.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D2D15F7ABD9008A8FBF /* BB9.png */; }; 40 | 5A796D3E15F7ABD9008A8FBF /* BB10.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D2E15F7ABD9008A8FBF /* BB10.png */; }; 41 | 5A796D3F15F7ABD9008A8FBF /* BB11.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D2F15F7ABD9008A8FBF /* BB11.png */; }; 42 | 5A796D4015F7ABD9008A8FBF /* BB12.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D3015F7ABD9008A8FBF /* BB12.png */; }; 43 | 5A796D4115F7ABD9008A8FBF /* BB13.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D3115F7ABD9008A8FBF /* BB13.png */; }; 44 | 5A796D4215F7ABD9008A8FBF /* BB14.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D3215F7ABD9008A8FBF /* BB14.png */; }; 45 | 5A796D4315F7ABD9008A8FBF /* BB15.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D3315F7ABD9008A8FBF /* BB15.png */; }; 46 | 5A796D4415F7ABD9008A8FBF /* BB16.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D3415F7ABD9008A8FBF /* BB16.png */; }; 47 | 5A796D4615F7AC61008A8FBF /* AA.gif in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D4515F7AC61008A8FBF /* AA.gif */; }; 48 | 5A796D4C15F7AE75008A8FBF /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A796D4B15F7AE75008A8FBF /* MobileCoreServices.framework */; }; 49 | 5A796D4E15F7AEA7008A8FBF /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A796D4D15F7AEA7008A8FBF /* ImageIO.framework */; }; 50 | 5A796D5015F7B077008A8FBF /* BB0.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A796D4F15F7B077008A8FBF /* BB0.png */; }; 51 | 5A8D914215F844F80078E2B4 /* fdgdf.gif in Resources */ = {isa = PBXBuildFile; fileRef = 5A8D914115F844F80078E2B4 /* fdgdf.gif */; }; 52 | 5A98411C168010900050D42D /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5A98411B168010900050D42D /* Default-568h@2x.png */; }; 53 | 5ACA4EDC1938636D00A6B8D3 /* OLImageResponseSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 5ACA4EDB1938636D00A6B8D3 /* OLImageResponseSerializer.m */; }; 54 | 5AEC556319D5E6E200EE94E5 /* google-io.gif in Resources */ = {isa = PBXBuildFile; fileRef = 5AEC556019D5E6E200EE94E5 /* google-io.gif */; }; 55 | 5AEC556419D5E6E200EE94E5 /* google-io@2x.gif in Resources */ = {isa = PBXBuildFile; fileRef = 5AEC556119D5E6E200EE94E5 /* google-io@2x.gif */; }; 56 | 5AEC556519D5E6E200EE94E5 /* google-io@3x.gif in Resources */ = {isa = PBXBuildFile; fileRef = 5AEC556219D5E6E200EE94E5 /* google-io@3x.gif */; }; 57 | 9CFBBE94194EE9D100DBE3AE /* OLImageStrictResponseSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CFBBE93194EE9D100DBE3AE /* OLImageStrictResponseSerializer.m */; }; 58 | F2B924CC4DF949A082919C1A /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D8B873DBE54D4E0AB5CC12D3 /* libPods.a */; }; 59 | /* End PBXBuildFile section */ 60 | 61 | /* Begin PBXFileReference section */ 62 | 07BB9C55170696E800E68171 /* 1.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 1.gif; sourceTree = ""; }; 63 | 07BB9C56170696E800E68171 /* 2.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 2.gif; sourceTree = ""; }; 64 | 07BB9C57170696E800E68171 /* 3.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 3.gif; sourceTree = ""; }; 65 | 07BB9C58170696E800E68171 /* 4.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 4.gif; sourceTree = ""; }; 66 | 07BB9C59170696E800E68171 /* 5.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 5.gif; sourceTree = ""; }; 67 | 07BB9C5A170696E800E68171 /* 6.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 6.gif; sourceTree = ""; }; 68 | 07BB9C5B170696E800E68171 /* 7.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 7.gif; sourceTree = ""; }; 69 | 07BB9C5C170696E800E68171 /* 8.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 8.gif; sourceTree = ""; }; 70 | 07BB9C5D170696E800E68171 /* 9.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 9.gif; sourceTree = ""; }; 71 | 07BB9C5E170696E800E68171 /* 10.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 10.gif; sourceTree = ""; }; 72 | 07CCC8E8170524130062371E /* AFImageRequestOperation+OLImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "AFImageRequestOperation+OLImage.h"; path = "Categories/AFImageRequestOperation+OLImage.h"; sourceTree = SOURCE_ROOT; }; 73 | 07CCC8E9170524130062371E /* AFImageRequestOperation+OLImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "AFImageRequestOperation+OLImage.m"; path = "Categories/AFImageRequestOperation+OLImage.m"; sourceTree = SOURCE_ROOT; }; 74 | 4A4DE572700BF683548BC30C /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 75 | 5A053BE115F844060014BF82 /* BLEH.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = BLEH.gif; sourceTree = ""; }; 76 | 5A1F4BB9165C449E00B61FCF /* OLImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OLImage.h; sourceTree = SOURCE_ROOT; }; 77 | 5A1F4BBA165C449E00B61FCF /* OLImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OLImage.m; sourceTree = SOURCE_ROOT; }; 78 | 5A1F4BBB165C449E00B61FCF /* OLImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OLImageView.h; sourceTree = SOURCE_ROOT; }; 79 | 5A1F4BBC165C449E00B61FCF /* OLImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OLImageView.m; sourceTree = SOURCE_ROOT; }; 80 | 5A2FFAA315F7F56100CEE5F6 /* notEven.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = notEven.gif; sourceTree = ""; }; 81 | 5A2FFAA615F800D500CEE5F6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 82 | 5A796CFD15F79EC7008A8FBF /* OLImageViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OLImageViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 83 | 5A796D0115F79EC7008A8FBF /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 84 | 5A796D0315F79EC7008A8FBF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 85 | 5A796D0515F79EC7008A8FBF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 86 | 5A796D0915F79EC7008A8FBF /* OLImageViewDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "OLImageViewDemo-Info.plist"; sourceTree = ""; }; 87 | 5A796D0B15F79EC7008A8FBF /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 88 | 5A796D0D15F79EC8008A8FBF /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 89 | 5A796D0F15F79EC8008A8FBF /* OLImageViewDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OLImageViewDemo-Prefix.pch"; sourceTree = ""; }; 90 | 5A796D1015F79EC8008A8FBF /* OLAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OLAppDelegate.h; sourceTree = ""; }; 91 | 5A796D1115F79EC8008A8FBF /* OLAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OLAppDelegate.m; sourceTree = ""; }; 92 | 5A796D2515F7ABD9008A8FBF /* BB1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB1.png; sourceTree = ""; }; 93 | 5A796D2615F7ABD9008A8FBF /* BB2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB2.png; sourceTree = ""; }; 94 | 5A796D2715F7ABD9008A8FBF /* BB3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB3.png; sourceTree = ""; }; 95 | 5A796D2815F7ABD9008A8FBF /* BB4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB4.png; sourceTree = ""; }; 96 | 5A796D2915F7ABD9008A8FBF /* BB5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB5.png; sourceTree = ""; }; 97 | 5A796D2A15F7ABD9008A8FBF /* BB6.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB6.png; sourceTree = ""; }; 98 | 5A796D2B15F7ABD9008A8FBF /* BB7.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB7.png; sourceTree = ""; }; 99 | 5A796D2C15F7ABD9008A8FBF /* BB8.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB8.png; sourceTree = ""; }; 100 | 5A796D2D15F7ABD9008A8FBF /* BB9.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB9.png; sourceTree = ""; }; 101 | 5A796D2E15F7ABD9008A8FBF /* BB10.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB10.png; sourceTree = ""; }; 102 | 5A796D2F15F7ABD9008A8FBF /* BB11.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB11.png; sourceTree = ""; }; 103 | 5A796D3015F7ABD9008A8FBF /* BB12.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB12.png; sourceTree = ""; }; 104 | 5A796D3115F7ABD9008A8FBF /* BB13.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB13.png; sourceTree = ""; }; 105 | 5A796D3215F7ABD9008A8FBF /* BB14.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB14.png; sourceTree = ""; }; 106 | 5A796D3315F7ABD9008A8FBF /* BB15.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB15.png; sourceTree = ""; }; 107 | 5A796D3415F7ABD9008A8FBF /* BB16.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB16.png; sourceTree = ""; }; 108 | 5A796D4515F7AC61008A8FBF /* AA.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = AA.gif; sourceTree = ""; }; 109 | 5A796D4B15F7AE75008A8FBF /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 110 | 5A796D4D15F7AEA7008A8FBF /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; 111 | 5A796D4F15F7B077008A8FBF /* BB0.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = BB0.png; sourceTree = ""; }; 112 | 5A8D914115F844F80078E2B4 /* fdgdf.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = fdgdf.gif; sourceTree = ""; }; 113 | 5A98411B168010900050D42D /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 114 | 5ACA4EDA1938636D00A6B8D3 /* OLImageResponseSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OLImageResponseSerializer.h; sourceTree = ""; }; 115 | 5ACA4EDB1938636D00A6B8D3 /* OLImageResponseSerializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OLImageResponseSerializer.m; sourceTree = ""; }; 116 | 5AEC556019D5E6E200EE94E5 /* google-io.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "google-io.gif"; sourceTree = ""; }; 117 | 5AEC556119D5E6E200EE94E5 /* google-io@2x.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "google-io@2x.gif"; sourceTree = ""; }; 118 | 5AEC556219D5E6E200EE94E5 /* google-io@3x.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "google-io@3x.gif"; sourceTree = ""; }; 119 | 9CFBBE92194EE9D100DBE3AE /* OLImageStrictResponseSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OLImageStrictResponseSerializer.h; sourceTree = ""; }; 120 | 9CFBBE93194EE9D100DBE3AE /* OLImageStrictResponseSerializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OLImageStrictResponseSerializer.m; sourceTree = ""; }; 121 | AEBC80445A15EBABE31A94E8 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 122 | CCF677081AE044F800A367EF /* OLImageViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OLImageViewDelegate.h; sourceTree = SOURCE_ROOT; }; 123 | D8B873DBE54D4E0AB5CC12D3 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 124 | /* End PBXFileReference section */ 125 | 126 | /* Begin PBXFrameworksBuildPhase section */ 127 | 5A796CFA15F79EC7008A8FBF /* Frameworks */ = { 128 | isa = PBXFrameworksBuildPhase; 129 | buildActionMask = 2147483647; 130 | files = ( 131 | 5A2FFAA715F800D500CEE5F6 /* QuartzCore.framework in Frameworks */, 132 | 5A796D4E15F7AEA7008A8FBF /* ImageIO.framework in Frameworks */, 133 | 5A796D4C15F7AE75008A8FBF /* MobileCoreServices.framework in Frameworks */, 134 | 5A796D0215F79EC7008A8FBF /* UIKit.framework in Frameworks */, 135 | 5A796D0415F79EC7008A8FBF /* Foundation.framework in Frameworks */, 136 | 5A796D0615F79EC7008A8FBF /* CoreGraphics.framework in Frameworks */, 137 | F2B924CC4DF949A082919C1A /* libPods.a in Frameworks */, 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXFrameworksBuildPhase section */ 142 | 143 | /* Begin PBXGroup section */ 144 | 07BB9C361706809C00E68171 /* Images */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | 5AEC556019D5E6E200EE94E5 /* google-io.gif */, 148 | 5AEC556119D5E6E200EE94E5 /* google-io@2x.gif */, 149 | 5AEC556219D5E6E200EE94E5 /* google-io@3x.gif */, 150 | 5A98411B168010900050D42D /* Default-568h@2x.png */, 151 | 07BB9C55170696E800E68171 /* 1.gif */, 152 | 07BB9C56170696E800E68171 /* 2.gif */, 153 | 07BB9C57170696E800E68171 /* 3.gif */, 154 | 07BB9C58170696E800E68171 /* 4.gif */, 155 | 07BB9C59170696E800E68171 /* 5.gif */, 156 | 07BB9C5A170696E800E68171 /* 6.gif */, 157 | 07BB9C5B170696E800E68171 /* 7.gif */, 158 | 07BB9C5C170696E800E68171 /* 8.gif */, 159 | 07BB9C5D170696E800E68171 /* 9.gif */, 160 | 07BB9C5E170696E800E68171 /* 10.gif */, 161 | 5A8D914115F844F80078E2B4 /* fdgdf.gif */, 162 | 5A053BE115F844060014BF82 /* BLEH.gif */, 163 | 5A2FFAA315F7F56100CEE5F6 /* notEven.gif */, 164 | 5A796D4515F7AC61008A8FBF /* AA.gif */, 165 | 5A796D4F15F7B077008A8FBF /* BB0.png */, 166 | 5A796D2515F7ABD9008A8FBF /* BB1.png */, 167 | 5A796D2615F7ABD9008A8FBF /* BB2.png */, 168 | 5A796D2715F7ABD9008A8FBF /* BB3.png */, 169 | 5A796D2815F7ABD9008A8FBF /* BB4.png */, 170 | 5A796D2915F7ABD9008A8FBF /* BB5.png */, 171 | 5A796D2A15F7ABD9008A8FBF /* BB6.png */, 172 | 5A796D2B15F7ABD9008A8FBF /* BB7.png */, 173 | 5A796D2C15F7ABD9008A8FBF /* BB8.png */, 174 | 5A796D2D15F7ABD9008A8FBF /* BB9.png */, 175 | 5A796D2E15F7ABD9008A8FBF /* BB10.png */, 176 | 5A796D2F15F7ABD9008A8FBF /* BB11.png */, 177 | 5A796D3015F7ABD9008A8FBF /* BB12.png */, 178 | 5A796D3115F7ABD9008A8FBF /* BB13.png */, 179 | 5A796D3215F7ABD9008A8FBF /* BB14.png */, 180 | 5A796D3315F7ABD9008A8FBF /* BB15.png */, 181 | 5A796D3415F7ABD9008A8FBF /* BB16.png */, 182 | ); 183 | path = Images; 184 | sourceTree = ""; 185 | }; 186 | 07CCC8E6170523B80062371E /* OLImageView */ = { 187 | isa = PBXGroup; 188 | children = ( 189 | 5A1F4BB9165C449E00B61FCF /* OLImage.h */, 190 | 5A1F4BBA165C449E00B61FCF /* OLImage.m */, 191 | CCF677081AE044F800A367EF /* OLImageViewDelegate.h */, 192 | 5A1F4BBB165C449E00B61FCF /* OLImageView.h */, 193 | 5A1F4BBC165C449E00B61FCF /* OLImageView.m */, 194 | 07CCC8E8170524130062371E /* AFImageRequestOperation+OLImage.h */, 195 | 07CCC8E9170524130062371E /* AFImageRequestOperation+OLImage.m */, 196 | ); 197 | name = OLImageView; 198 | path = OLImageViewDemo; 199 | sourceTree = ""; 200 | }; 201 | 5A796CF215F79EC7008A8FBF = { 202 | isa = PBXGroup; 203 | children = ( 204 | 5ACA4ED91938636D00A6B8D3 /* AFNetworking */, 205 | 07CCC8E6170523B80062371E /* OLImageView */, 206 | 5A796D0715F79EC7008A8FBF /* OLImageViewDemo */, 207 | 5A796D0015F79EC7008A8FBF /* Frameworks */, 208 | 5A796CFE15F79EC7008A8FBF /* Products */, 209 | CC174B41C3D1D9A892201DF2 /* Pods */, 210 | ); 211 | sourceTree = ""; 212 | }; 213 | 5A796CFE15F79EC7008A8FBF /* Products */ = { 214 | isa = PBXGroup; 215 | children = ( 216 | 5A796CFD15F79EC7008A8FBF /* OLImageViewDemo.app */, 217 | ); 218 | name = Products; 219 | sourceTree = ""; 220 | }; 221 | 5A796D0015F79EC7008A8FBF /* Frameworks */ = { 222 | isa = PBXGroup; 223 | children = ( 224 | 5A2FFAA615F800D500CEE5F6 /* QuartzCore.framework */, 225 | 5A796D4D15F7AEA7008A8FBF /* ImageIO.framework */, 226 | 5A796D4B15F7AE75008A8FBF /* MobileCoreServices.framework */, 227 | 5A796D0115F79EC7008A8FBF /* UIKit.framework */, 228 | 5A796D0315F79EC7008A8FBF /* Foundation.framework */, 229 | 5A796D0515F79EC7008A8FBF /* CoreGraphics.framework */, 230 | D8B873DBE54D4E0AB5CC12D3 /* libPods.a */, 231 | ); 232 | name = Frameworks; 233 | sourceTree = ""; 234 | }; 235 | 5A796D0715F79EC7008A8FBF /* OLImageViewDemo */ = { 236 | isa = PBXGroup; 237 | children = ( 238 | 5A796D1015F79EC8008A8FBF /* OLAppDelegate.h */, 239 | 5A796D1115F79EC8008A8FBF /* OLAppDelegate.m */, 240 | 5A796D0815F79EC7008A8FBF /* Supporting Files */, 241 | ); 242 | path = OLImageViewDemo; 243 | sourceTree = ""; 244 | }; 245 | 5A796D0815F79EC7008A8FBF /* Supporting Files */ = { 246 | isa = PBXGroup; 247 | children = ( 248 | 07BB9C361706809C00E68171 /* Images */, 249 | 5A796D0915F79EC7008A8FBF /* OLImageViewDemo-Info.plist */, 250 | 5A796D0A15F79EC7008A8FBF /* InfoPlist.strings */, 251 | 5A796D0D15F79EC8008A8FBF /* main.m */, 252 | 5A796D0F15F79EC8008A8FBF /* OLImageViewDemo-Prefix.pch */, 253 | ); 254 | name = "Supporting Files"; 255 | sourceTree = ""; 256 | }; 257 | 5ACA4ED91938636D00A6B8D3 /* AFNetworking */ = { 258 | isa = PBXGroup; 259 | children = ( 260 | 5ACA4EDA1938636D00A6B8D3 /* OLImageResponseSerializer.h */, 261 | 5ACA4EDB1938636D00A6B8D3 /* OLImageResponseSerializer.m */, 262 | 9CFBBE92194EE9D100DBE3AE /* OLImageStrictResponseSerializer.h */, 263 | 9CFBBE93194EE9D100DBE3AE /* OLImageStrictResponseSerializer.m */, 264 | ); 265 | path = AFNetworking; 266 | sourceTree = SOURCE_ROOT; 267 | }; 268 | CC174B41C3D1D9A892201DF2 /* Pods */ = { 269 | isa = PBXGroup; 270 | children = ( 271 | AEBC80445A15EBABE31A94E8 /* Pods.debug.xcconfig */, 272 | 4A4DE572700BF683548BC30C /* Pods.release.xcconfig */, 273 | ); 274 | name = Pods; 275 | sourceTree = ""; 276 | }; 277 | /* End PBXGroup section */ 278 | 279 | /* Begin PBXNativeTarget section */ 280 | 5A796CFC15F79EC7008A8FBF /* OLImageViewDemo */ = { 281 | isa = PBXNativeTarget; 282 | buildConfigurationList = 5A796D1515F79EC8008A8FBF /* Build configuration list for PBXNativeTarget "OLImageViewDemo" */; 283 | buildPhases = ( 284 | 0E63FB56DF2A4928818EC1E9 /* Check Pods Manifest.lock */, 285 | 5A796CF915F79EC7008A8FBF /* Sources */, 286 | 5A796CFA15F79EC7008A8FBF /* Frameworks */, 287 | 5A796CFB15F79EC7008A8FBF /* Resources */, 288 | 1EAA632824374C8989B9ABE2 /* Copy Pods Resources */, 289 | ); 290 | buildRules = ( 291 | ); 292 | dependencies = ( 293 | ); 294 | name = OLImageViewDemo; 295 | productName = OLImageViewDemo; 296 | productReference = 5A796CFD15F79EC7008A8FBF /* OLImageViewDemo.app */; 297 | productType = "com.apple.product-type.application"; 298 | }; 299 | /* End PBXNativeTarget section */ 300 | 301 | /* Begin PBXProject section */ 302 | 5A796CF415F79EC7008A8FBF /* Project object */ = { 303 | isa = PBXProject; 304 | attributes = { 305 | CLASSPREFIX = OL; 306 | LastUpgradeCheck = 0450; 307 | ORGANIZATIONNAME = "Onda Labs"; 308 | }; 309 | buildConfigurationList = 5A796CF715F79EC7008A8FBF /* Build configuration list for PBXProject "OLImageViewDemo" */; 310 | compatibilityVersion = "Xcode 3.2"; 311 | developmentRegion = English; 312 | hasScannedForEncodings = 0; 313 | knownRegions = ( 314 | en, 315 | ); 316 | mainGroup = 5A796CF215F79EC7008A8FBF; 317 | productRefGroup = 5A796CFE15F79EC7008A8FBF /* Products */; 318 | projectDirPath = ""; 319 | projectRoot = ""; 320 | targets = ( 321 | 5A796CFC15F79EC7008A8FBF /* OLImageViewDemo */, 322 | ); 323 | }; 324 | /* End PBXProject section */ 325 | 326 | /* Begin PBXResourcesBuildPhase section */ 327 | 5A796CFB15F79EC7008A8FBF /* Resources */ = { 328 | isa = PBXResourcesBuildPhase; 329 | buildActionMask = 2147483647; 330 | files = ( 331 | 5A796D0C15F79EC7008A8FBF /* InfoPlist.strings in Resources */, 332 | 5A796D3515F7ABD9008A8FBF /* BB1.png in Resources */, 333 | 5A796D3615F7ABD9008A8FBF /* BB2.png in Resources */, 334 | 5A796D3715F7ABD9008A8FBF /* BB3.png in Resources */, 335 | 5A796D3815F7ABD9008A8FBF /* BB4.png in Resources */, 336 | 5A796D3915F7ABD9008A8FBF /* BB5.png in Resources */, 337 | 5AEC556419D5E6E200EE94E5 /* google-io@2x.gif in Resources */, 338 | 5A796D3A15F7ABD9008A8FBF /* BB6.png in Resources */, 339 | 5A796D3B15F7ABD9008A8FBF /* BB7.png in Resources */, 340 | 5A796D3C15F7ABD9008A8FBF /* BB8.png in Resources */, 341 | 5A796D3D15F7ABD9008A8FBF /* BB9.png in Resources */, 342 | 5A796D3E15F7ABD9008A8FBF /* BB10.png in Resources */, 343 | 5AEC556319D5E6E200EE94E5 /* google-io.gif in Resources */, 344 | 5A796D3F15F7ABD9008A8FBF /* BB11.png in Resources */, 345 | 5A796D4015F7ABD9008A8FBF /* BB12.png in Resources */, 346 | 5A796D4115F7ABD9008A8FBF /* BB13.png in Resources */, 347 | 5A796D4215F7ABD9008A8FBF /* BB14.png in Resources */, 348 | 5A796D4315F7ABD9008A8FBF /* BB15.png in Resources */, 349 | 5A796D4415F7ABD9008A8FBF /* BB16.png in Resources */, 350 | 5A796D4615F7AC61008A8FBF /* AA.gif in Resources */, 351 | 5A796D5015F7B077008A8FBF /* BB0.png in Resources */, 352 | 5A2FFAA415F7F56100CEE5F6 /* notEven.gif in Resources */, 353 | 5A053BE215F844060014BF82 /* BLEH.gif in Resources */, 354 | 5A8D914215F844F80078E2B4 /* fdgdf.gif in Resources */, 355 | 5A98411C168010900050D42D /* Default-568h@2x.png in Resources */, 356 | 07BB9C5F170696E800E68171 /* 1.gif in Resources */, 357 | 07BB9C60170696E800E68171 /* 2.gif in Resources */, 358 | 07BB9C61170696E800E68171 /* 3.gif in Resources */, 359 | 07BB9C62170696E800E68171 /* 4.gif in Resources */, 360 | 5AEC556519D5E6E200EE94E5 /* google-io@3x.gif in Resources */, 361 | 07BB9C63170696E800E68171 /* 5.gif in Resources */, 362 | 07BB9C64170696E800E68171 /* 6.gif in Resources */, 363 | 07BB9C65170696E800E68171 /* 7.gif in Resources */, 364 | 07BB9C66170696E800E68171 /* 8.gif in Resources */, 365 | 07BB9C67170696E800E68171 /* 9.gif in Resources */, 366 | 07BB9C68170696E800E68171 /* 10.gif in Resources */, 367 | ); 368 | runOnlyForDeploymentPostprocessing = 0; 369 | }; 370 | /* End PBXResourcesBuildPhase section */ 371 | 372 | /* Begin PBXShellScriptBuildPhase section */ 373 | 0E63FB56DF2A4928818EC1E9 /* Check Pods Manifest.lock */ = { 374 | isa = PBXShellScriptBuildPhase; 375 | buildActionMask = 2147483647; 376 | files = ( 377 | ); 378 | inputPaths = ( 379 | ); 380 | name = "Check Pods Manifest.lock"; 381 | outputPaths = ( 382 | ); 383 | runOnlyForDeploymentPostprocessing = 0; 384 | shellPath = /bin/sh; 385 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 386 | showEnvVarsInLog = 0; 387 | }; 388 | 1EAA632824374C8989B9ABE2 /* Copy Pods Resources */ = { 389 | isa = PBXShellScriptBuildPhase; 390 | buildActionMask = 2147483647; 391 | files = ( 392 | ); 393 | inputPaths = ( 394 | ); 395 | name = "Copy Pods Resources"; 396 | outputPaths = ( 397 | ); 398 | runOnlyForDeploymentPostprocessing = 0; 399 | shellPath = /bin/sh; 400 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 401 | showEnvVarsInLog = 0; 402 | }; 403 | /* End PBXShellScriptBuildPhase section */ 404 | 405 | /* Begin PBXSourcesBuildPhase section */ 406 | 5A796CF915F79EC7008A8FBF /* Sources */ = { 407 | isa = PBXSourcesBuildPhase; 408 | buildActionMask = 2147483647; 409 | files = ( 410 | 9CFBBE94194EE9D100DBE3AE /* OLImageStrictResponseSerializer.m in Sources */, 411 | 5ACA4EDC1938636D00A6B8D3 /* OLImageResponseSerializer.m in Sources */, 412 | 5A796D0E15F79EC8008A8FBF /* main.m in Sources */, 413 | 5A796D1215F79EC8008A8FBF /* OLAppDelegate.m in Sources */, 414 | 5A1F4BBD165C449E00B61FCF /* OLImage.m in Sources */, 415 | 5A1F4BBE165C449E00B61FCF /* OLImageView.m in Sources */, 416 | ); 417 | runOnlyForDeploymentPostprocessing = 0; 418 | }; 419 | /* End PBXSourcesBuildPhase section */ 420 | 421 | /* Begin PBXVariantGroup section */ 422 | 5A796D0A15F79EC7008A8FBF /* InfoPlist.strings */ = { 423 | isa = PBXVariantGroup; 424 | children = ( 425 | 5A796D0B15F79EC7008A8FBF /* en */, 426 | ); 427 | name = InfoPlist.strings; 428 | sourceTree = ""; 429 | }; 430 | /* End PBXVariantGroup section */ 431 | 432 | /* Begin XCBuildConfiguration section */ 433 | 5A796D1315F79EC8008A8FBF /* Debug */ = { 434 | isa = XCBuildConfiguration; 435 | buildSettings = { 436 | ALWAYS_SEARCH_USER_PATHS = NO; 437 | CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; 438 | CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; 439 | CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; 440 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 441 | CLANG_CXX_LIBRARY = "libc++"; 442 | CLANG_ENABLE_OBJC_ARC = YES; 443 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 444 | CLANG_WARN_EMPTY_BODY = YES; 445 | CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; 446 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 447 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 448 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 449 | COPY_PHASE_STRIP = NO; 450 | GCC_C_LANGUAGE_STANDARD = gnu99; 451 | GCC_DYNAMIC_NO_PIC = NO; 452 | GCC_OPTIMIZATION_LEVEL = 0; 453 | GCC_PREPROCESSOR_DEFINITIONS = ( 454 | "DEBUG=1", 455 | "$(inherited)", 456 | ); 457 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 458 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 459 | GCC_WARN_SHADOW = YES; 460 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 461 | GCC_WARN_UNKNOWN_PRAGMAS = YES; 462 | GCC_WARN_UNUSED_LABEL = YES; 463 | GCC_WARN_UNUSED_VARIABLE = YES; 464 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 465 | ONLY_ACTIVE_ARCH = YES; 466 | SDKROOT = iphoneos; 467 | TARGETED_DEVICE_FAMILY = "1,2"; 468 | }; 469 | name = Debug; 470 | }; 471 | 5A796D1415F79EC8008A8FBF /* Release */ = { 472 | isa = XCBuildConfiguration; 473 | buildSettings = { 474 | ALWAYS_SEARCH_USER_PATHS = NO; 475 | CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; 476 | CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; 477 | CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; 478 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 479 | CLANG_CXX_LIBRARY = "libc++"; 480 | CLANG_ENABLE_OBJC_ARC = YES; 481 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 482 | CLANG_WARN_EMPTY_BODY = YES; 483 | CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES; 484 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 485 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 486 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 487 | COPY_PHASE_STRIP = YES; 488 | GCC_C_LANGUAGE_STANDARD = gnu99; 489 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 490 | GCC_WARN_SHADOW = YES; 491 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 492 | GCC_WARN_UNKNOWN_PRAGMAS = YES; 493 | GCC_WARN_UNUSED_LABEL = YES; 494 | GCC_WARN_UNUSED_VARIABLE = YES; 495 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 496 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 497 | SDKROOT = iphoneos; 498 | TARGETED_DEVICE_FAMILY = "1,2"; 499 | VALIDATE_PRODUCT = YES; 500 | }; 501 | name = Release; 502 | }; 503 | 5A796D1615F79EC8008A8FBF /* Debug */ = { 504 | isa = XCBuildConfiguration; 505 | baseConfigurationReference = AEBC80445A15EBABE31A94E8 /* Pods.debug.xcconfig */; 506 | buildSettings = { 507 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 508 | GCC_PREFIX_HEADER = "OLImageViewDemo/OLImageViewDemo-Prefix.pch"; 509 | INFOPLIST_FILE = "OLImageViewDemo/OLImageViewDemo-Info.plist"; 510 | PRODUCT_NAME = "$(TARGET_NAME)"; 511 | WRAPPER_EXTENSION = app; 512 | }; 513 | name = Debug; 514 | }; 515 | 5A796D1715F79EC8008A8FBF /* Release */ = { 516 | isa = XCBuildConfiguration; 517 | baseConfigurationReference = 4A4DE572700BF683548BC30C /* Pods.release.xcconfig */; 518 | buildSettings = { 519 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 520 | GCC_PREFIX_HEADER = "OLImageViewDemo/OLImageViewDemo-Prefix.pch"; 521 | INFOPLIST_FILE = "OLImageViewDemo/OLImageViewDemo-Info.plist"; 522 | PRODUCT_NAME = "$(TARGET_NAME)"; 523 | WRAPPER_EXTENSION = app; 524 | }; 525 | name = Release; 526 | }; 527 | /* End XCBuildConfiguration section */ 528 | 529 | /* Begin XCConfigurationList section */ 530 | 5A796CF715F79EC7008A8FBF /* Build configuration list for PBXProject "OLImageViewDemo" */ = { 531 | isa = XCConfigurationList; 532 | buildConfigurations = ( 533 | 5A796D1315F79EC8008A8FBF /* Debug */, 534 | 5A796D1415F79EC8008A8FBF /* Release */, 535 | ); 536 | defaultConfigurationIsVisible = 0; 537 | defaultConfigurationName = Release; 538 | }; 539 | 5A796D1515F79EC8008A8FBF /* Build configuration list for PBXNativeTarget "OLImageViewDemo" */ = { 540 | isa = XCConfigurationList; 541 | buildConfigurations = ( 542 | 5A796D1615F79EC8008A8FBF /* Debug */, 543 | 5A796D1715F79EC8008A8FBF /* Release */, 544 | ); 545 | defaultConfigurationIsVisible = 0; 546 | defaultConfigurationName = Release; 547 | }; 548 | /* End XCConfigurationList section */ 549 | }; 550 | rootObject = 5A796CF415F79EC7008A8FBF /* Project object */; 551 | } 552 | -------------------------------------------------------------------------------- /OLImageViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OLImageViewDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /OLImageViewDemo/Images/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/1.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/10.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/2.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/3.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/4.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/5.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/6.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/7.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/7.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/8.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/9.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/9.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/AA.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/AA.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB0.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB1.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB10.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB11.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB12.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB13.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB14.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB15.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB16.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB2.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB3.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB4.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB5.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB6.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB7.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB8.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BB9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BB9.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/BLEH.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/BLEH.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/Default-568h@2x.png -------------------------------------------------------------------------------- /OLImageViewDemo/Images/fdgdf.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/fdgdf.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/google-io.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/google-io.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/google-io@2x.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/google-io@2x.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/google-io@3x.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/google-io@3x.gif -------------------------------------------------------------------------------- /OLImageViewDemo/Images/notEven.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dtorres/OLImageView/2160c32351691f16dca51ecc6885c2740808aa8f/OLImageViewDemo/Images/notEven.gif -------------------------------------------------------------------------------- /OLImageViewDemo/OLAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // OLAppDelegate.h 3 | // OLImageViewDemo 4 | // 5 | // Created by Diego Torres on 9/5/12. 6 | // Copyright (c) 2012 Onda Labs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OLAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /OLImageViewDemo/OLAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // OLAppDelegate.m 3 | // OLImageViewDemo 4 | // 5 | // Created by Diego Torres on 9/5/12. 6 | // Copyright (c) 2012 Onda Labs. All rights reserved. 7 | // 8 | 9 | #import "OLAppDelegate.h" 10 | #import "OLImageView.h" 11 | #import "OLImage.h" 12 | 13 | #import 14 | #import "OLImageResponseSerializer.h" 15 | #import "OLImageStrictResponseSerializer.h" 16 | 17 | #import "OLImageViewDelegate.h" 18 | 19 | #define OLDemoShowAnimationTickers 0 20 | 21 | @interface OLAppDelegate () 22 | 23 | @property (nonatomic, getter=isRunning) BOOL running; 24 | 25 | @end 26 | 27 | @implementation OLAppDelegate 28 | 29 | -(BOOL)imageViewShouldStartAnimating:(OLImageView *)imageView { 30 | 31 | return self.isRunning; 32 | } 33 | 34 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 35 | { 36 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 37 | 38 | UIViewController *normalAnimatedVC = [UIViewController new]; 39 | normalAnimatedVC.title = @"UIImageView"; 40 | UIImageView *imv = [[UIImageView alloc] initWithImage:[UIImage animatedImageNamed:@"BB" duration:1.6]]; 41 | normalAnimatedVC.view = imv; 42 | 43 | UIViewController *magicAnimatedVC = [UIViewController new]; 44 | magicAnimatedVC.title = @"OLImageView"; 45 | 46 | OLImageView *Aimv = [[OLImageView alloc] initWithImage:[OLImage imageNamed:@"notEven.gif"]]; 47 | [Aimv setFrame:CGRectMake(0, 0, 160, 160)]; 48 | [Aimv setUserInteractionEnabled:YES]; 49 | [Aimv addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]]; 50 | [magicAnimatedVC.view addSubview:Aimv]; 51 | 52 | Aimv = [[OLImageView alloc] initWithImage:[OLImage imageNamed:@"google-io"]]; 53 | [Aimv setFrame:CGRectMake(0, 160, 160, 160)]; 54 | [Aimv setUserInteractionEnabled:YES]; 55 | [Aimv addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]]; 56 | [magicAnimatedVC.view addSubview:Aimv]; 57 | 58 | Aimv = [[OLImageView alloc] initWithImage:[OLImage imageNamed:@"fdgdf.gif"]]; 59 | [Aimv setFrame:CGRectMake(160, 0, 160, 160)]; 60 | [Aimv setUserInteractionEnabled:YES]; 61 | [Aimv addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]]; 62 | [magicAnimatedVC.view addSubview:Aimv]; 63 | 64 | Aimv = [[OLImageView alloc] initWithImage:[OLImage imageNamed:@"AA.gif"]]; 65 | Aimv.delegate = self; 66 | [Aimv setFrame:CGRectMake(160, 160, 160, 160)]; 67 | [Aimv setUserInteractionEnabled:YES]; 68 | [Aimv addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]]; 69 | [magicAnimatedVC.view addSubview:Aimv]; 70 | 71 | #if OLDemoShowAnimationTickers 72 | // GIFs from http://blog.fenrir-inc.com/us/2012/02/theyre-different-how-to-match-the-animation-rate-of-gif-files-accross-browsers.html 73 | for (NSUInteger i = 1; i <= 10; i++) { 74 | NSString *filename = [NSString stringWithFormat:@"%u.gif", i]; 75 | OLImageView *frameCountImage = [[OLImageView alloc] initWithImage:[OLImage imageNamed:filename]]; 76 | [frameCountImage setFrame:CGRectMake((i - 1) * 32, 320, 32, 32)]; 77 | [magicAnimatedVC.view addSubview:frameCountImage]; 78 | } 79 | #endif 80 | 81 | UIViewController *magicAnimatedVCnet = [UIViewController new]; 82 | magicAnimatedVCnet.title = @"OLImageView+AFNet2"; 83 | UIImageView *imgV = [UIImageView new]; 84 | imgV.imageResponseSerializer = [OLImageResponseSerializer new]; 85 | imgV.frame = CGRectMake(0, 0, 320, 240); 86 | [magicAnimatedVCnet.view addSubview:imgV]; 87 | 88 | // First image uses easy one-for-all serializer and is suitable for all images, losing some AFNetworking behavior 89 | [imgV setImageWithURL:[NSURL URLWithString:@"http://24.media.tumblr.com/9a7e2652afde1fbe7b1d2e978be64765/tumblr_mke4w2g7C31qz8x31o1_400.gif"]]; 90 | 91 | imgV = [UIImageView new]; 92 | AFCompoundResponseSerializer *compoundSerializer = [AFCompoundResponseSerializer compoundSerializerWithResponseSerializers:@[[OLImageStrictResponseSerializer new], imgV.imageResponseSerializer]]; 93 | imgV.imageResponseSerializer = compoundSerializer; 94 | imgV.frame = CGRectMake(0, 240, 320, 240); 95 | [magicAnimatedVCnet.view addSubview:imgV]; 96 | 97 | // Second image uses compound serializer, is suitable for both gifs and images and support any number of serializers 98 | [imgV setImageWithURL:[NSURL URLWithString:@"http://24.media.tumblr.com/9a7e2652afde1fbe7b1d2e978be64765/tumblr_mke4w2g7C31qz8x31o1_400.gif"]]; 99 | 100 | UITabBarController *tbc = [[UITabBarController alloc] init]; 101 | [tbc setViewControllers:@[normalAnimatedVC, magicAnimatedVC, magicAnimatedVCnet]]; 102 | 103 | self.window.rootViewController = tbc; 104 | self.window.backgroundColor = [UIColor whiteColor]; 105 | [self.window makeKeyAndVisible]; 106 | 107 | return YES; 108 | } 109 | 110 | - (void)handleTap:(UITapGestureRecognizer *)gestRecon 111 | { 112 | OLImageView *imageView = (OLImageView *)gestRecon.view; 113 | if (self.isRunning) { 114 | self.running = NO; 115 | NSLog(@"STOP"); 116 | [imageView stopAnimating]; 117 | } else { 118 | self.running = YES; 119 | NSLog(@"START"); 120 | [imageView startAnimating]; 121 | } 122 | } 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /OLImageViewDemo/OLImageViewDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.ondalabs.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /OLImageViewDemo/OLImageViewDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'OLImageViewDemo' target in the 'OLImageViewDemo' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /OLImageViewDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /OLImageViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // OLImageViewDemo 4 | // 5 | // Created by Diego Torres on 9/5/12. 6 | // Copyright (c) 2012 Onda Labs. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "OLAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([OLAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, "7.0" 2 | 3 | pod "AFNetworking/UIKit" -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking/NSURLConnection (2.3.1): 3 | - AFNetworking/Reachability 4 | - AFNetworking/Security 5 | - AFNetworking/Serialization 6 | - AFNetworking/NSURLSession (2.3.1): 7 | - AFNetworking/Reachability 8 | - AFNetworking/Security 9 | - AFNetworking/Serialization 10 | - AFNetworking/Reachability (2.3.1) 11 | - AFNetworking/Security (2.3.1) 12 | - AFNetworking/Serialization (2.3.1) 13 | - AFNetworking/UIKit (2.3.1): 14 | - AFNetworking/NSURLConnection 15 | - AFNetworking/NSURLSession 16 | 17 | DEPENDENCIES: 18 | - AFNetworking/UIKit 19 | 20 | SPEC CHECKSUMS: 21 | AFNetworking: 05b9f6e3aa5ac45bc383b4bb108ef338080a26c7 22 | 23 | COCOAPODS: 0.36.3 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | IMPORTANT: This project is no longer being maintained, please have a look at [FLAnimatedImage](https://github.com/Flipboard/FLAnimatedImage) 3 | 4 | # OLImageView (and OLImage) 5 | Everybody loves a good GIF. Unfortunately, Apple's implementation of UIImage doesn't support animated GIFs. OLImage and OLImageView are drop-in replacements for UIImage and UIImageView with really good support for animated GIFs. 6 | 7 | ## Why did we do this? 8 | There are many other classes to do this already, but they just don't work the way they should. Most existing classes: 9 | 10 | - Divide the delay between frames evenly, all the time (even if the file specifies different per-frame delays) 11 | - Load frames synchronously, which freezes up the main thread (especially when loading large files) and only show anything when all the frames are loaded 12 | 13 | We tried to fix some of these issues, but we found that the experience still didn't feel quite right. After a little of digging, we found out that browsers change the frame delays on certain conditions. This implementation adopts these conditions to provide an experience that is consistent with the WebKit rendering of an animated GIF. 14 | 15 | ## How to use 16 | Add the header and replace UIImageView with OLImageView. 17 | 18 | **Example** 19 | 20 | // Before (in your View Controller in this example) 21 | 22 | - (void)loadView 23 | { 24 | [super loadView]; 25 | self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,200,200)]; 26 | [self.view addSubview:self.imageView]; 27 | } 28 | 29 | 30 | // After 31 | 32 | #import "OLImageView.h" 33 | 34 | - (void)loadView 35 | { 36 | [super loadView]; 37 | self.imageView = [[OLImageView alloc] initWithFrame:CGRectMake(0,0,200,200)]; 38 | [self.view addSubview:self.imageView]; 39 | } 40 | 41 | Now, when you create your image instances to put in the view, you should do it with the data. 42 | 43 | **Example** 44 | 45 | - (void)loadReceivedImageData:(NSData *)data; 46 | { 47 | UIImage *image = [OLImage imageWithData:data]; 48 | self.imageView.image = image; 49 | } 50 | 51 | ## Integration with other libs 52 | ### AFNetworking 53 | This repo includes a category to integrate OLImage with AFNetworking v1.x [UIImageView category](https://github.com/AFNetworking/AFNetworking/blob/1.x/AFNetworking/UIImageView+AFNetworking.h), which provides caching and remote URL setters. 54 | To use this, just import the category where you will be using OLImageView with the AFNetworking category. 55 | 56 | Users of AFNetworking 2.x can use any of the two provided image reponse serializers. `OLImageResponseSerializer` is a drop-in replacement for the standard AFNetworking serializer, which simply creates OLImage instances for every data: 57 | 58 | imageView.imageResponseSerializer = [[OLImageResponseSerializer alloc] init]; 59 | 60 | Those who want to keep default `AFImageResponseSerializer` behavior or need to chain many serializers, there's a strict one, only accepting image/gif: `OLImageStrictResponseSerializer`. Serializer chaining might look like this: 61 | 62 | imageView.imageResponseSerializer = 63 | [AFCompoundResponseSerializer compoundSerializerWithResponseSerializers: 64 | @[[[OLImageStrictResponseSerializer alloc] init], imageView.imageResponseSerializer]]; 65 | 66 | You are more than welcome to send pull requests with categories or subclasses that integrate OLImage with other libraries. 67 | 68 | ## Help us make this better 69 | Found a bug? A typo? Can you make the decoding faster? Feel free to fork this and send us a pull request (or file an issue). 70 | --------------------------------------------------------------------------------