[
  {
    "path": ".gitignore",
    "content": "# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nproject.xcworkspace\n!default.xcworkspace\nxcuserdata\n*.xccheckout\n*.moved-aside\nDerivedData\n*.hmap\n*.ipa\n*.xcuserstate\n*.xcscmblueprint\n\n# CocoaPods\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control\n#\nPods/\nPodfile.lock\n"
  },
  {
    "path": ".swift-version",
    "content": "2.3\n"
  },
  {
    "path": ".travis.yml",
    "content": "\r\nlanguage: objective-c\r\n\r\ncache:\r\n  - bundler\r\n  - cocoapods\r\n\r\nosx_image: xcode7.1\r\n\r\nbefore_install:\r\n\r\n    - export LANG=en_US.UTF-8\r\n    - env\r\n    - locale\r\n    - gem install cocoapods --no-rdoc --no-ri --no-document --quiet\r\n    - pod --version\r\n    - pod setup --silent > /dev/null\r\n    - pod repo update --silent\r\n    \r\nscript:\r\n\r\n    - pod lib lint --allow-warnings\r\n    - xctool -workspace FlyImage.xcworkspace -scheme 'FlyImage' -sdk iphonesimulator -arch i386 build\r\n    \r\n    - pod install --project-directory=Examples    \r\n    - xctool -workspace './Examples/FlyImageView.xcworkspace' -scheme 'FlyImageView' -sdk iphonesimulator -arch i386 build\r\n    - xctool -workspace './Examples/FlyImageView.xcworkspace' -scheme 'FlyImageIconView' -sdk iphonesimulator -arch i386 build\r\n    - xctool -workspace './Examples/FlyImageView.xcworkspace' -scheme 'WebP' -sdk iphonesimulator -arch i386 build\r\n    - xctool -workspace './Examples/FlyImageView.xcworkspace' -scheme 'SingleView' -sdk iphonesimulator -arch i386 build\r\n    \r\n    - xcodebuild -workspace FlyImage.xcworkspace -scheme 'FlyImageTests' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' test\r\n                \r\n\r\n    "
  },
  {
    "path": "Examples/FlyImageIconView/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  FlyImageIconView\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n\n\n@end\n\n"
  },
  {
    "path": "Examples/FlyImageIconView/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  FlyImageIconView\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n#import \"RootViewController.h\"\n#import \"TriditionTableViewCell.h\"\n#import \"SDWebImageTableViewCell.h\"\n#import \"FlyImageIconLayerTableViewCell.h\"\n#import \"FlyImageIconViewTableViewCell.h\"\n#import \"FlyImage.h\"\n\n@interface AppDelegate ()\n\n@end\n\n@implementation AppDelegate\n\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n\t\n\tself.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n\tself.window.backgroundColor = [UIColor whiteColor];\n\t\n\tRootViewController *rootViewController = [[RootViewController alloc] init];\n\trootViewController.suffix = @\"_tn.jpg\";\n\trootViewController.cellsPerRow = 10;\n\trootViewController.heightOfCell = self.window.bounds.size.width / rootViewController.cellsPerRow;\n\trootViewController.activeIndex = 3;\n\trootViewController.cells = @[ @{\n\t\t\t\t\t\t\t\t\t  @\"class\": [TriditionTableViewCell class],\n\t\t\t\t\t\t\t\t\t  @\"title\": @\"UIKit\"\n\t\t\t\t\t\t\t\t\t  },@{\n\t\t\t\t\t\t\t\t\t  @\"class\": [SDWebImageTableViewCell class],\n\t\t\t\t\t\t\t\t\t  @\"title\": @\"SDWebImage\"\n\t\t\t\t\t\t\t\t\t  }, @{\n\t\t\t\t\t\t\t\t\t  @\"class\": [FlyImageIconViewTableViewCell class],\n\t\t\t\t\t\t\t\t\t  @\"title\": @\"FlyImageIconView\"\n\t\t\t\t\t\t\t\t\t  }, @{\n\t\t\t\t\t\t\t\t\t  @\"class\": [FlyImageIconLayerTableViewCell class],\n\t\t\t\t\t\t\t\t\t  @\"title\": @\"FlyImageIconLayer\"\n\t\t\t\t\t\t\t\t\t  }];\n\t\n\tself.window.rootViewController = rootViewController;\n\t[self.window makeKeyAndVisible];\n\t\n\treturn YES;\n}\n\n- (void)applicationWillResignActive:(UIApplication *)application {\n\t// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.\n\t// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.\n}\n\n- (void)applicationDidEnterBackground:(UIApplication *)application {\n\t// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.\n\t// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.\n}\n\n- (void)applicationWillEnterForeground:(UIApplication *)application {\n\t// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.\n}\n\n- (void)applicationDidBecomeActive:(UIApplication *)application {\n\t// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.\n}\n\n- (void)applicationWillTerminate:(UIApplication *)application {\n\t// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.\n}\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageIconView/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>UILaunchStoryboardName</key>\n\t<string>Launch Screen</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UIRequiresFullScreen</key>\n\t<true/>\n\t<key>UIStatusBarHidden</key>\n\t<true/>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Examples/FlyImageIconView/main.m",
    "content": "//\n//  main.m\n//  FlyImageIconView\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n\t@autoreleasepool {\n\t    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n\t}\n}\n"
  },
  {
    "path": "Examples/FlyImageView/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  FlyImageView\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n\n\n@end\n\n"
  },
  {
    "path": "Examples/FlyImageView/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  FlyImageView\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n#import \"RootViewController.h\"\n#import \"TriditionTableViewCell.h\"\n#import \"FlyImageTableViewCell.h\"\n#import \"FlyImageLayerTableViewCell.h\"\n#import \"SDWebImageTableViewCell.h\"\n#import \"FlyImage.h\"\n\n@interface AppDelegate ()\n\n@end\n\n@implementation AppDelegate\n\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n\tself.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n\tself.window.backgroundColor = [UIColor whiteColor];\n\t\n\t[FlyImageCache sharedInstance].autoDismissImage = YES;\n\t\n\tRootViewController *rootViewController = [[RootViewController alloc] init];\n\trootViewController.suffix = @\".jpg\";\n\trootViewController.heightOfCell = 150;\n\trootViewController.cellsPerRow = 1;\n\trootViewController.activeIndex = 3;\n\trootViewController.cells = @[ @{\n\t\t\t\t\t\t\t\t\t  @\"class\": [TriditionTableViewCell class],\n\t\t\t\t\t\t\t\t\t  @\"title\": @\"UIKit\"\n\t\t\t\t\t\t\t\t\t  },@{\n\t\t\t\t\t\t\t\t\t  @\"class\": [SDWebImageTableViewCell class],\n\t\t\t\t\t\t\t\t\t  @\"title\": @\"SDWebImage\"\n\t\t\t\t\t\t\t\t\t  } ,@{\n\t\t\t\t\t\t\t\t\t  @\"class\": [FlyImageTableViewCell class],\n\t\t\t\t\t\t\t\t\t  @\"title\": @\"FlyImageView\"\n\t\t\t\t\t\t\t\t\t  } ,@{\n\t\t\t\t\t\t\t\t\t  @\"class\": [FlyImageLayerTableViewCell class],\n\t\t\t\t\t\t\t\t\t  @\"title\": @\"FlyImageLayer\"\n\t\t\t\t\t\t\t\t\t  }];\n\t\n\tself.window.rootViewController = rootViewController;\n\t[self.window makeKeyAndVisible];\n\t\n\treturn YES;\n}\n\n- (void)applicationWillResignActive:(UIApplication *)application {\n\t// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.\n\t// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.\n}\n\n- (void)applicationDidEnterBackground:(UIApplication *)application {\n\t// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.\n\t// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.\n}\n\n- (void)applicationWillEnterForeground:(UIApplication *)application {\n\t// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.\n}\n\n- (void)applicationDidBecomeActive:(UIApplication *)application {\n\t// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.\n}\n\n- (void)applicationWillTerminate:(UIApplication *)application {\n\t// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.\n}\n\n- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {\n\tNSLog(@\"Memory Warning\");\n}\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/BaseTableViewCell.h",
    "content": "//\n//  BaseTableViewCell.h\n//  Demo\n//\n//  Created by Norris Tong on 4/15/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface BaseTableViewCell : UITableViewCell\n\n- (void)displayImageWithPhotos:(NSArray *)photos;\n\n- (id)imageViewWithFrame:(CGRect)frame;\n\n- (void)renderImageView:(id)imageView url:(NSURL *)url;\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/BaseTableViewCell.m",
    "content": "//\n//  BaseTableViewCell.m\n//  Demo\n//\n//  Created by Norris Tong on 4/15/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"BaseTableViewCell.h\"\n\n@implementation BaseTableViewCell {\n    NSMutableArray *_imageViews;\n    NSArray *_photos;\n}\n\n- (void)displayImageWithPhotos:(NSArray *)photos {\n    \n    if ( _imageViews == nil ) {\n        NSInteger photoCount = [photos count];\n        _imageViews = [[NSMutableArray alloc] initWithCapacity:photoCount];\n        \n        CGRect frame = self.frame;\n        CGFloat itemWidth = floor(frame.size.width / photoCount);\n        CGFloat padding = 2;\n        for (int i=0; i<photoCount; i++) {\n            id imageView = [self imageViewWithFrame:CGRectMake(i * itemWidth + padding, padding, itemWidth-padding*2, frame.size.height - padding*2)];\n            [_imageViews addObject:imageView];\n        }\n    }\n    \n    _photos = photos;\n    [self setNeedsLayout];\n}\n\n- (id)imageViewWithFrame:(CGRect)frame {\n    return nil;\n}\n\n- (void)renderImageView:(id)imageView url:(NSURL *)url {\n}\n\n#pragma mark - Configuring the View Hierarchy\n- (void)layoutSubviews {\n    [super layoutSubviews];\n    \n    for (int i=0; i<MIN([_photos count], [_imageViews count]); i++) {\n        id imageView = [_imageViews objectAtIndex:i];\n        NSURL *url = [_photos objectAtIndex:i];\n        [self renderImageView:imageView url:url];\n    }\n}\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageIconLayerTableViewCell.h",
    "content": "//\n//  FlyImageIconLayerTableViewCell.h\n//  FlyImageView\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import \"BaseTableViewCell.h\"\n\n@interface FlyImageIconLayerTableViewCell : BaseTableViewCell\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageIconLayerTableViewCell.m",
    "content": "//\n//  FlyImageIconLayerTableViewCell.m\n//  FlyImageView\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import \"FlyImageIconLayerTableViewCell.h\"\n#import \"FlyImage.h\"\n\n@implementation FlyImageIconLayerTableViewCell\n\n- (id)imageViewWithFrame:(CGRect)frame {\n\tCALayer *imageLayer = [[CALayer alloc] init];\n\timageLayer.frame = frame;\n\timageLayer.contentsGravity = kCAGravityResizeAspectFill;\n\timageLayer.cornerRadius = 10;\n\t[self.layer addSublayer:imageLayer];\n\t\n\treturn imageLayer;\n}\n\n- (void)renderImageView:(id)imageView url:(NSURL *)url {\n\t((CALayer *)imageView).iconURL = url;\n}\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageIconViewTableViewCell.h",
    "content": "//\n//  FlyImageIconViewTableViewCell.h\n//  FlyImageView\n//\n//  Created by Ye Tong on 5/3/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import \"BaseTableViewCell.h\"\n\n@interface FlyImageIconViewTableViewCell : BaseTableViewCell\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageIconViewTableViewCell.m",
    "content": "//\n//  FlyImageIconViewTableViewCell.m\n//  FlyImageView\n//\n//  Created by Ye Tong on 5/3/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import \"FlyImageIconViewTableViewCell.h\"\n#import \"FlyImage.h\"\n\n@implementation FlyImageIconViewTableViewCell\n\n- (id)imageViewWithFrame:(CGRect)frame {\n\tUIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];\n\timageView.contentMode = UIViewContentModeScaleAspectFill;\n\timageView.layer.cornerRadius = 10;\n\t[self addSubview:imageView];\n\t\n\treturn imageView;\n}\n\n- (void)renderImageView:(id)imageView url:(NSURL *)url {\n\t((UIImageView *)imageView).iconURL = url;\n}\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageLayerTableViewCell.h",
    "content": "//\n//  FlyImageLayerTableViewCell.h\n//  Demo\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"BaseTableViewCell.h\"\n\n@interface FlyImageLayerTableViewCell : BaseTableViewCell\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageLayerTableViewCell.m",
    "content": "//\n//  FlyImageLayerTableViewCell.m\n//  Demo\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"FlyImageLayerTableViewCell.h\"\n#import \"FlyImage.h\"\n\n@implementation FlyImageLayerTableViewCell\n\n- (id)imageViewWithFrame:(CGRect)frame {\n\tCALayer *imageView = [[CALayer alloc] init];\n\timageView.frame = frame;\n\timageView.contentsGravity = kCAGravityResizeAspectFill;\n\timageView.cornerRadius = 10;\n\t[self.layer addSublayer:imageView];\n\t\n\treturn imageView;\n}\n\n- (void)renderImageView:(id)imageView url:(NSURL *)url {\n\t((CALayer *)imageView).imageURL = url;\n}\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageTableViewCell.h",
    "content": "//\n//  FlyImageTableViewCell.h\n//  Demo\n//\n//  Created by Norris Tong on 4/14/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"BaseTableViewCell.h\"\n\n@interface FlyImageTableViewCell : BaseTableViewCell\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageTableViewCell.m",
    "content": "//\n//  FlyImageTableViewCell.m\n//  Demo\n//\n//  Created by Norris Tong on 4/14/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"FlyImageTableViewCell.h\"\n#import \"FlyImage.h\"\n#import \"ProgressImageView.h\"\n\n@implementation FlyImageTableViewCell\n\n- (id)imageViewWithFrame:(CGRect)frame {\n    ProgressImageView *imageView = [[ProgressImageView alloc] initWithFrame:frame];\n    imageView.contentMode = UIViewContentModeScaleAspectFill;\n    imageView.layer.cornerRadius = 10;\n    [self addSubview:imageView];\n\t\n    return imageView;\n}\n\n- (void)renderImageView:(id)imageView url:(NSURL *)url {\n\t[imageView setImageURL:url];\n}\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/SDWebImageTableViewCell.h",
    "content": "//\n//  SDWebImageTableViewCell.h\n//  Demo\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"BaseTableViewCell.h\"\n\n@interface SDWebImageTableViewCell : BaseTableViewCell\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/SDWebImageTableViewCell.m",
    "content": "//\n//  SDWebImageTableViewCell.m\n//  Demo\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"SDWebImageTableViewCell.h\"\n#import \"UIImageView+WebCache.h\"\n\n@implementation SDWebImageTableViewCell\n\n- (id)imageViewWithFrame:(CGRect)frame {\n\tUIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];\n\timageView.contentMode = UIViewContentModeScaleAspectFill;\n\timageView.layer.cornerRadius = 10;\n\t[self addSubview:imageView];\n\t\n\treturn imageView;\n}\n\n- (void)renderImageView:(id)imageView url:(NSURL *)url {\n\t[((UIImageView *)imageView) sd_setImageWithURL:url];\n}\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/TriditionTableViewCell.h",
    "content": "//\n//  TriditionTableViewCell.h\n//  Demo\n//\n//  Created by Norris Tong on 4/14/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"BaseTableViewCell.h\"\n\n@interface TriditionTableViewCell : BaseTableViewCell\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Cells/TriditionTableViewCell.m",
    "content": "//\n//  TriditionTableViewCell.m\n//  Demo\n//\n//  Created by Norris Tong on 4/14/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"TriditionTableViewCell.h\"\n#import \"FlyImageDownloader.h\"\n#import \"FlyImageDataFileManager.h\"\n#import \"FlyImageCache.h\"\n#import <objc/runtime.h>\n#import <CommonCrypto/CommonDigest.h>\n\n@interface NSString (Extension)\n- (NSString *)md5;\n@end\n\n@implementation NSString (Extension)\n- (NSString *)md5 {\n    const char *cStr = [self UTF8String];\n    unsigned char result[CC_MD5_DIGEST_LENGTH];\n    CC_MD5(cStr, (CC_LONG)strlen(cStr), result); // This is the md5 call\n    return [NSString stringWithFormat:@\"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\",\n            result[0],\n            result[1],\n            result[2],\n            result[3],\n            result[4],\n            result[5],\n            result[6],\n            result[7],\n            result[8],\n            result[9],\n            result[10],\n            result[11],\n            result[12],\n            result[13],\n            result[14],\n            result[15]];\n}\n@end\n\n@implementation TriditionTableViewCell\n\n- (id)imageViewWithFrame:(CGRect)frame {\n    UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];\n    imageView.contentMode = UIViewContentModeScaleAspectFill;\n    imageView.layer.masksToBounds = YES;\n    imageView.layer.cornerRadius = 10;\n    [self addSubview:imageView];\n\t\n    return imageView;\n}\n\n- (void)renderImageView:(id)imageView url:(NSURL *)url {\n\t\n\tNSString *key = url.absoluteString;\n    if ( [[FlyImageCache sharedInstance] isImageExistWithKey:key] ) {\n\t\t\n\t\tNSString *path = [[FlyImageCache sharedInstance] imagePathWithKey:key];\n        NSURL *url = [NSURL fileURLWithPath:path];\n        [self doRenderImageView:imageView url:url];\n        \n    }else{\n        NSURLRequest *request = [NSURLRequest requestWithURL:url];\n        [[FlyImageDownloader sharedInstance] downloadImageForURLRequest:request progress:nil success:^(NSURLRequest *request, NSURL *filePath) {\n            \n            [[FlyImageCache sharedInstance] addImageWithKey:key filename:[filePath lastPathComponent] completed:^(NSString *key, UIImage *image) {\n\t\t\t\t((UIImageView *)imageView).image = image;\n\t\t\t}];\n\t\t\t\n        } failed:^(NSURLRequest *request, NSError *error) {\n            NSLog(@\"occur error = %@\", error );\n        }];\n\t\t\n\t\t((UIImageView *)imageView).image = nil;\n    }\n}\n\n- (void)doRenderImageView:(UIImageView *)imageView url:(NSURL *)url {\n    NSData *data = [NSData dataWithContentsOfURL:url];\n    UIImage *image = [UIImage imageWithData:data];\n    imageView.image = image;\n}\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>UILaunchStoryboardName</key>\n\t<string>Launch Screen</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UIRequiresFullScreen</key>\n\t<true/>\n\t<key>UIStatusBarHidden</key>\n\t<true/>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Examples/FlyImageView/Launch Screen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"10117\" systemVersion=\"15G31\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"10085\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Llm-lL-Icb\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xb3-aO-Qok\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "Examples/FlyImageView/ProgressImageView.h",
    "content": "//\n//  ProgressImageView.h\n//  FlyImageView\n//\n//  Created by Ye Tong on 8/12/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface ProgressImageView : UIImageView\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/ProgressImageView.m",
    "content": "//\n//  ProgressImageView.m\n//  FlyImageView\n//\n//  Created by Ye Tong on 8/12/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import \"ProgressImageView.h\"\n#import \"FlyImage.h\"\n\n@implementation ProgressImageView\n\n- (instancetype)initWithFrame:(CGRect)frame {\n\tif ( self = [super initWithFrame:frame] ) {\n\t\t[self addObserver:self forKeyPath:@\"downloadingPercentage\" options:NSKeyValueObservingOptionNew context:nil];\n\t}\n\t\n\treturn self;\n}\n\n- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {\n\tif ([keyPath isEqualToString:@\"downloadingPercentage\"]) {\n\t\tNSLog(@\"downloadingURL : %@\", self.downloadingURL );\n\t\tNSLog(@\"downloadingPercentage : %f\", self.downloadingPercentage );\n\t}\n}\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/RootViewController.h",
    "content": "//\n//  RootViewController.h\n//  Demo\n//\n//  Created by Ye Tong on 3/24/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface RootViewController : UIViewController\n\n@property (nonatomic, strong) NSArray *cells;\n@property (nonatomic, assign) CGFloat heightOfCell;\n@property (nonatomic, assign) NSInteger cellsPerRow;\n@property (nonatomic, assign) NSInteger activeIndex;\n@property (nonatomic, copy) NSString *suffix;\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/RootViewController.m",
    "content": "//\n//  RootViewController.m\n//  Demo\n//\n//  Created by Ye Tong on 3/24/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"RootViewController.h\"\n#import \"BaseTableViewCell.h\"\n#import \"SDImageCache.h\"\n#import <SDWebImageManager.h>\n\n@interface RootViewController () <UITableViewDataSource, UITableViewDelegate, SDWebImageManagerDelegate>\n\n@property (nonatomic, assign) CGFloat itemWidth;\n@property (nonatomic, assign) CGFloat itemHeight;\n\n@end\n\n@implementation RootViewController {\n\tUITableView *_tableView;\n\tUISegmentedControl *_segment;\n\t\n    NSMutableArray *_imageURLs;\n    NSMutableArray *_cells;\n    NSMutableArray *_indentifiers;\n}\n\n- (instancetype)init {\n\tif (self = [super init]) {\n\t\t_cells = [[NSMutableArray alloc] init];\n\t\t_indentifiers = [[NSMutableArray alloc] init];\n\t\t_activeIndex = 0;\n\t}\n\treturn self;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n\tself.view.backgroundColor = [UIColor whiteColor];\n\t\n\t// setup image paths\n\t_imageURLs = [[NSMutableArray alloc] init];\n\tfor (int i=0; i<100; i++) {\n\t\tNSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@\"https://flyimage.oss-us-west-1.aliyuncs.com/%d%@\", i, self.suffix ]];\n\t\t[_imageURLs addObject:url];\n\t}\n\t\n\tCGFloat segmentHeight = 30;\n\tCGRect bounds = self.view.bounds;\n\t\n\t_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, bounds.size.width, bounds.size.height-segmentHeight)\n\t\t\t\t\t\t\t\t\t\t\t  style:UITableViewStylePlain];\n\t_tableView.opaque = YES;\n\t_tableView.directionalLockEnabled = YES;\n\t_tableView.backgroundColor = [UIColor clearColor];\n\t_tableView.allowsSelection = NO;\n\t_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;\n\t_tableView.dataSource = self;\n\t_tableView.delegate = self;\n\t\n\tNSMutableArray *items = [NSMutableArray array];\n\tfor (NSDictionary *info in _cells) {\n\t\t[items addObject: [info objectForKey:@\"title\"]];\n\t\t\n\t\tClass class = [info objectForKey:@\"class\"];\n\t\tNSString *indentifier = NSStringFromClass(class);\n\t\t[_indentifiers addObject:indentifier];\n\t\t[_tableView registerClass:class forCellReuseIdentifier:indentifier];\n\t}\n\t[self.view addSubview:_tableView];\n\t\n\tNSDictionary *textAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:10], NSFontAttributeName, nil];\n\t[[UISegmentedControl appearance] setTitleTextAttributes:textAttributes forState:UIControlStateNormal];\n\t\n\t_segment = [[UISegmentedControl alloc] initWithItems:items];\n\t_segment.backgroundColor = [UIColor whiteColor];\n\t_segment.frame = CGRectMake(0, bounds.size.height - segmentHeight, bounds.size.width, segmentHeight);\n\t[_segment setSelectedSegmentIndex:_activeIndex];\n\t[_segment addTarget:self action:@selector(onTapSegment) forControlEvents:UIControlEventValueChanged];\n\t[self.view addSubview:_segment];\n    \n    SDWebImageManager *sdManager = [SDWebImageManager sharedManager];\n    sdManager.delegate = self;\n    \n    _itemWidth = floor(self.view.frame.size.width / _cellsPerRow) - 4;\n    _itemHeight = _heightOfCell - 4;\n}\n\n#pragma mark - SDWebImageManagerDelegate\n\n- (UIImage *)imageManager:(SDWebImageManager *)imageManager transformDownloadedImage:(UIImage *)image withURL:(NSURL *)imageURL{\n    UIGraphicsBeginImageContextWithOptions(CGSizeMake(_itemWidth, _heightOfCell), NO, [UIScreen mainScreen].scale);\n    \n    CGRect box = CGRectMake(0, 0, _itemWidth, _itemHeight);\n    [[UIBezierPath bezierPathWithRoundedRect:box cornerRadius:10.f] addClip];\n    [image drawInRect:box];\n    \n    UIImage* ret = UIGraphicsGetImageFromCurrentImageContext();\n    \n    UIGraphicsEndImageContext();\n    return ret;\n}\n\n- (BOOL)prefersStatusBarHidden {\n\treturn YES;\n}\n\n- (void)onTapSegment {\n\t_activeIndex = _segment.selectedSegmentIndex;\n\t\n\t[_tableView reloadData];\n}\n\n#pragma mark - UITableViewDataSource\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\n\treturn 2000;\n}\n\n- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {\n\treturn self.heightOfCell;\n}\n\n// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\n\t\n    NSInteger startIndex = ([indexPath row] * self.cellsPerRow) % [_imageURLs count];\n    NSInteger count = MIN(self.cellsPerRow, [_imageURLs count] - startIndex);\n    NSArray *photos = [_imageURLs subarrayWithRange:NSMakeRange(startIndex, count)];\n    \n\tBaseTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:_indentifiers[_activeIndex] forIndexPath:indexPath];\n    [cell displayImageWithPhotos:photos];\n\n    return cell;\n}\n\n@end\n"
  },
  {
    "path": "Examples/FlyImageView/main.m",
    "content": "//\n//  main.m\n//  FlyImageView\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n\t@autoreleasepool {\n\t    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n\t}\n}\n"
  },
  {
    "path": "Examples/FlyImageView.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t7539169AF2FD0C6CD1ED1213 /* libPods-FlyImageIconView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F9C3948F7DFDB6E2FE5F0B0 /* libPods-FlyImageIconView.a */; };\n\t\t8E45DB317D60C68FC813142D /* libPods-FlyImageView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DCBFE3EE450E44921AFAF53 /* libPods-FlyImageView.a */; };\n\t\t977F44737DA3E198C81BF6F4 /* libPods-SingleView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0280F6E421151FBFAE698C23 /* libPods-SingleView.a */; };\n\t\tCEE17C7A1B5057E6682927EF /* libPods-WebP.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EC1098E069AA6CA893D0F2C /* libPods-WebP.a */; };\n\t\tDD2EDB131D61E6C30085C9E3 /* ProgressImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8E088D1D5DD5BD00FEBC3A /* ProgressImageView.m */; };\n\t\tDD8E088E1D5DD5BD00FEBC3A /* ProgressImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8E088D1D5DD5BD00FEBC3A /* ProgressImageView.m */; };\n\t\tDD9D97481CC5044D008F279E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D97471CC5044D008F279E /* main.m */; };\n\t\tDD9D974B1CC5044D008F279E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D974A1CC5044D008F279E /* AppDelegate.m */; };\n\t\tDDBECFCD1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDBECFCC1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.m */; };\n\t\tDDBED17A1CD8C5D600EC9263 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DDBED1791CD8C5D600EC9263 /* main.m */; };\n\t\tDDBED17D1CD8C5D600EC9263 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DDBED17C1CD8C5D600EC9263 /* AppDelegate.m */; };\n\t\tDDBED19B1CD8C70C00EC9263 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1381CD0831F00EEC549 /* RootViewController.m */; };\n\t\tDDBED19C1CD8C71100EC9263 /* BaseTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F13C1CD0832400EEC549 /* BaseTableViewCell.m */; };\n\t\tDDBED19D1CD8C71900EC9263 /* TriditionTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1481CD0832400EEC549 /* TriditionTableViewCell.m */; };\n\t\tDDBED19E1CD8C71B00EC9263 /* SDWebImageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1461CD0832400EEC549 /* SDWebImageTableViewCell.m */; };\n\t\tDDBED19F1CD8C72A00EC9263 /* FlyImageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1441CD0832400EEC549 /* FlyImageTableViewCell.m */; };\n\t\tDDBED1A01CD8C72E00EC9263 /* FlyImageLayerTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1421CD0832400EEC549 /* FlyImageLayerTableViewCell.m */; };\n\t\tDDBED1A11CD8C76700EC9263 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDD1F1501CD083B300EEC549 /* Default-568h@2x.png */; };\n\t\tDDD1F1391CD0831F00EEC549 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1381CD0831F00EEC549 /* RootViewController.m */; };\n\t\tDDD1F1491CD0832400EEC549 /* BaseTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F13C1CD0832400EEC549 /* BaseTableViewCell.m */; };\n\t\tDDD1F14C1CD0832400EEC549 /* FlyImageLayerTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1421CD0832400EEC549 /* FlyImageLayerTableViewCell.m */; };\n\t\tDDD1F14D1CD0832400EEC549 /* FlyImageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1441CD0832400EEC549 /* FlyImageTableViewCell.m */; };\n\t\tDDD1F14E1CD0832400EEC549 /* SDWebImageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1461CD0832400EEC549 /* SDWebImageTableViewCell.m */; };\n\t\tDDD1F14F1CD0832400EEC549 /* TriditionTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1481CD0832400EEC549 /* TriditionTableViewCell.m */; };\n\t\tDDD1F1511CD083B300EEC549 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDD1F1501CD083B300EEC549 /* Default-568h@2x.png */; };\n\t\tDDD1F15A1CD084E500EEC549 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1591CD084E500EEC549 /* main.m */; };\n\t\tDDD1F15D1CD084E500EEC549 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F15C1CD084E500EEC549 /* AppDelegate.m */; };\n\t\tDDD1F18F1CD0872D00EEC549 /* BaseTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F13C1CD0832400EEC549 /* BaseTableViewCell.m */; };\n\t\tDDD1F1911CD0872D00EEC549 /* SDWebImageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1461CD0832400EEC549 /* SDWebImageTableViewCell.m */; };\n\t\tDDD1F1931CD0872D00EEC549 /* TriditionTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1481CD0832400EEC549 /* TriditionTableViewCell.m */; };\n\t\tDDD1F1941CD08D1E00EEC549 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1381CD0831F00EEC549 /* RootViewController.m */; };\n\t\tDDD1F1951CD08E7D00EEC549 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDD1F1501CD083B300EEC549 /* Default-568h@2x.png */; };\n\t\tDDD1F1A01CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F19F1CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.m */; };\n\t\tDDD8FB601D59EB9200821392 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */; };\n\t\tDDD8FB611D59EB9200821392 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */; };\n\t\tDDD8FB621D59EB9200821392 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */; };\n\t\tDDD8FB631D59EB9200821392 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */; };\n\t\tDDDEF4321CE0AF4600C8366C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDEF4311CE0AF4600C8366C /* main.m */; };\n\t\tDDDEF4351CE0AF4600C8366C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDEF4341CE0AF4600C8366C /* AppDelegate.m */; };\n\t\tDDDEF4381CE0AF4600C8366C /* SingleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDEF4371CE0AF4600C8366C /* SingleViewController.m */; };\n\t\tDDDEF4451CE0B8AA00C8366C /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDD1F1501CD083B300EEC549 /* Default-568h@2x.png */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t0280F6E421151FBFAE698C23 /* libPods-SingleView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = \"libPods-SingleView.a\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t02F5D49EB862BEC96204662A /* Pods-FlyImageIconView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-FlyImageIconView.release.xcconfig\"; path = \"Pods/Target Support Files/Pods-FlyImageIconView/Pods-FlyImageIconView.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t33A4E8609F3283491E3DD133 /* Pods-SingleView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-SingleView.release.xcconfig\"; path = \"Pods/Target Support Files/Pods-SingleView/Pods-SingleView.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t3ABB5A3F814E3BFC95A513BD /* Pods-FlyImageView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-FlyImageView.release.xcconfig\"; path = \"Pods/Target Support Files/Pods-FlyImageView/Pods-FlyImageView.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t4EC1098E069AA6CA893D0F2C /* libPods-WebP.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = \"libPods-WebP.a\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t5F9C3948F7DFDB6E2FE5F0B0 /* libPods-FlyImageIconView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = \"libPods-FlyImageIconView.a\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t7D3083C3FEEB3316F9CCCF92 /* Pods-FlyImageIconView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-FlyImageIconView.debug.xcconfig\"; path = \"Pods/Target Support Files/Pods-FlyImageIconView/Pods-FlyImageIconView.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t841CA4D45E6400A9646A0F66 /* Pods-FlyImageView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-FlyImageView.debug.xcconfig\"; path = \"Pods/Target Support Files/Pods-FlyImageView/Pods-FlyImageView.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t9DCBFE3EE450E44921AFAF53 /* libPods-FlyImageView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = \"libPods-FlyImageView.a\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tD95E1058D32716446EB3DC84 /* Pods-WebP.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-WebP.debug.xcconfig\"; path = \"Pods/Target Support Files/Pods-WebP/Pods-WebP.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tDD8E088C1D5DD5BD00FEBC3A /* ProgressImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressImageView.h; path = ../ProgressImageView.h; sourceTree = \"<group>\"; };\n\t\tDD8E088D1D5DD5BD00FEBC3A /* ProgressImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressImageView.m; path = ../ProgressImageView.m; sourceTree = \"<group>\"; };\n\t\tDD9D97431CC5044D008F279E /* FlyImageView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FlyImageView.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tDD9D97471CC5044D008F279E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\tDD9D97491CC5044D008F279E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\tDD9D974A1CC5044D008F279E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\tDD9D97571CC5044D008F279E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tDDBECFCB1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageIconViewTableViewCell.h; sourceTree = \"<group>\"; };\n\t\tDDBECFCC1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageIconViewTableViewCell.m; sourceTree = \"<group>\"; };\n\t\tDDBED1761CD8C5D600EC9263 /* WebP.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WebP.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tDDBED1791CD8C5D600EC9263 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\tDDBED17B1CD8C5D600EC9263 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\tDDBED17C1CD8C5D600EC9263 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\tDDBED1891CD8C5D600EC9263 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tDDD1F1371CD0831F00EEC549 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = \"<group>\"; };\n\t\tDDD1F1381CD0831F00EEC549 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = \"<group>\"; };\n\t\tDDD1F13B1CD0832400EEC549 /* BaseTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseTableViewCell.h; sourceTree = \"<group>\"; };\n\t\tDDD1F13C1CD0832400EEC549 /* BaseTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseTableViewCell.m; sourceTree = \"<group>\"; };\n\t\tDDD1F1411CD0832400EEC549 /* FlyImageLayerTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageLayerTableViewCell.h; sourceTree = \"<group>\"; };\n\t\tDDD1F1421CD0832400EEC549 /* FlyImageLayerTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageLayerTableViewCell.m; sourceTree = \"<group>\"; };\n\t\tDDD1F1431CD0832400EEC549 /* FlyImageTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageTableViewCell.h; sourceTree = \"<group>\"; };\n\t\tDDD1F1441CD0832400EEC549 /* FlyImageTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageTableViewCell.m; sourceTree = \"<group>\"; };\n\t\tDDD1F1451CD0832400EEC549 /* SDWebImageTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDWebImageTableViewCell.h; sourceTree = \"<group>\"; };\n\t\tDDD1F1461CD0832400EEC549 /* SDWebImageTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTableViewCell.m; sourceTree = \"<group>\"; };\n\t\tDDD1F1471CD0832400EEC549 /* TriditionTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TriditionTableViewCell.h; sourceTree = \"<group>\"; };\n\t\tDDD1F1481CD0832400EEC549 /* TriditionTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TriditionTableViewCell.m; sourceTree = \"<group>\"; };\n\t\tDDD1F1501CD083B300EEC549 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = \"Default-568h@2x.png\"; path = \"../Default-568h@2x.png\"; sourceTree = \"<group>\"; };\n\t\tDDD1F1561CD084E500EEC549 /* FlyImageIconView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FlyImageIconView.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tDDD1F1591CD084E500EEC549 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\tDDD1F15B1CD084E500EEC549 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\tDDD1F15C1CD084E500EEC549 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\tDDD1F1691CD084E500EEC549 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tDDD1F19E1CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageIconLayerTableViewCell.h; sourceTree = \"<group>\"; };\n\t\tDDD1F19F1CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageIconLayerTableViewCell.m; sourceTree = \"<group>\"; };\n\t\tDDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = \"Launch Screen.storyboard\"; sourceTree = \"<group>\"; };\n\t\tDDDEF42E1CE0AF4600C8366C /* SingleView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SingleView.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tDDDEF4311CE0AF4600C8366C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\tDDDEF4331CE0AF4600C8366C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\tDDDEF4341CE0AF4600C8366C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\tDDDEF4361CE0AF4600C8366C /* SingleViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SingleViewController.h; sourceTree = \"<group>\"; };\n\t\tDDDEF4371CE0AF4600C8366C /* SingleViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SingleViewController.m; sourceTree = \"<group>\"; };\n\t\tDDDEF4411CE0AF4600C8366C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tE8620E15B0D1F42DDE6C37AA /* Pods-WebP.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-WebP.release.xcconfig\"; path = \"Pods/Target Support Files/Pods-WebP/Pods-WebP.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tFF39DAB46C23D364F5631D94 /* Pods-SingleView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-SingleView.debug.xcconfig\"; path = \"Pods/Target Support Files/Pods-SingleView/Pods-SingleView.debug.xcconfig\"; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\tDD9D97401CC5044D008F279E /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t8E45DB317D60C68FC813142D /* libPods-FlyImageView.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDDBED1731CD8C5D600EC9263 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tCEE17C7A1B5057E6682927EF /* libPods-WebP.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDDD1F1531CD084E500EEC549 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t7539169AF2FD0C6CD1ED1213 /* libPods-FlyImageIconView.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDDDEF42B1CE0AF4600C8366C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t977F44737DA3E198C81BF6F4 /* libPods-SingleView.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t3F7EFE6AE8450C9D550265DA /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7D3083C3FEEB3316F9CCCF92 /* Pods-FlyImageIconView.debug.xcconfig */,\n\t\t\t\t02F5D49EB862BEC96204662A /* Pods-FlyImageIconView.release.xcconfig */,\n\t\t\t\t841CA4D45E6400A9646A0F66 /* Pods-FlyImageView.debug.xcconfig */,\n\t\t\t\t3ABB5A3F814E3BFC95A513BD /* Pods-FlyImageView.release.xcconfig */,\n\t\t\t\tFF39DAB46C23D364F5631D94 /* Pods-SingleView.debug.xcconfig */,\n\t\t\t\t33A4E8609F3283491E3DD133 /* Pods-SingleView.release.xcconfig */,\n\t\t\t\tD95E1058D32716446EB3DC84 /* Pods-WebP.debug.xcconfig */,\n\t\t\t\tE8620E15B0D1F42DDE6C37AA /* Pods-WebP.release.xcconfig */,\n\t\t\t);\n\t\t\tname = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t566B055403ECA67AB6D690C2 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5F9C3948F7DFDB6E2FE5F0B0 /* libPods-FlyImageIconView.a */,\n\t\t\t\t9DCBFE3EE450E44921AFAF53 /* libPods-FlyImageView.a */,\n\t\t\t\t0280F6E421151FBFAE698C23 /* libPods-SingleView.a */,\n\t\t\t\t4EC1098E069AA6CA893D0F2C /* libPods-WebP.a */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDD9D973A1CC5044D008F279E = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDD9D97451CC5044D008F279E /* FlyImageView */,\n\t\t\t\tDDD1F1571CD084E500EEC549 /* FlyImageIconView */,\n\t\t\t\tDDBED1771CD8C5D600EC9263 /* WebP */,\n\t\t\t\tDDDEF42F1CE0AF4600C8366C /* SingleView */,\n\t\t\t\tDD9D97441CC5044D008F279E /* Products */,\n\t\t\t\t3F7EFE6AE8450C9D550265DA /* Pods */,\n\t\t\t\t566B055403ECA67AB6D690C2 /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDD9D97441CC5044D008F279E /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDD9D97431CC5044D008F279E /* FlyImageView.app */,\n\t\t\t\tDDD1F1561CD084E500EEC549 /* FlyImageIconView.app */,\n\t\t\t\tDDBED1761CD8C5D600EC9263 /* WebP.app */,\n\t\t\t\tDDDEF42E1CE0AF4600C8366C /* SingleView.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDD9D97451CC5044D008F279E /* FlyImageView */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDDD1F13A1CD0832400EEC549 /* Cells */,\n\t\t\t\tDD9D97491CC5044D008F279E /* AppDelegate.h */,\n\t\t\t\tDD9D974A1CC5044D008F279E /* AppDelegate.m */,\n\t\t\t\tDDD1F1371CD0831F00EEC549 /* RootViewController.h */,\n\t\t\t\tDDD1F1381CD0831F00EEC549 /* RootViewController.m */,\n\t\t\t\tDD9D97571CC5044D008F279E /* Info.plist */,\n\t\t\t\tDD9D97461CC5044D008F279E /* Supporting Files */,\n\t\t\t\tDDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */,\n\t\t\t);\n\t\t\tpath = FlyImageView;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDD9D97461CC5044D008F279E /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDDD1F1501CD083B300EEC549 /* Default-568h@2x.png */,\n\t\t\t\tDD9D97471CC5044D008F279E /* main.m */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDDBED1771CD8C5D600EC9263 /* WebP */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDDBED17B1CD8C5D600EC9263 /* AppDelegate.h */,\n\t\t\t\tDDBED17C1CD8C5D600EC9263 /* AppDelegate.m */,\n\t\t\t\tDDBED1891CD8C5D600EC9263 /* Info.plist */,\n\t\t\t\tDDBED1781CD8C5D600EC9263 /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = WebP;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDDBED1781CD8C5D600EC9263 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDDBED1791CD8C5D600EC9263 /* main.m */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDDD1F13A1CD0832400EEC549 /* Cells */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDDD1F13B1CD0832400EEC549 /* BaseTableViewCell.h */,\n\t\t\t\tDDD1F13C1CD0832400EEC549 /* BaseTableViewCell.m */,\n\t\t\t\tDDD1F1411CD0832400EEC549 /* FlyImageLayerTableViewCell.h */,\n\t\t\t\tDDD1F1421CD0832400EEC549 /* FlyImageLayerTableViewCell.m */,\n\t\t\t\tDDD1F1431CD0832400EEC549 /* FlyImageTableViewCell.h */,\n\t\t\t\tDDD1F1441CD0832400EEC549 /* FlyImageTableViewCell.m */,\n\t\t\t\tDDD1F1451CD0832400EEC549 /* SDWebImageTableViewCell.h */,\n\t\t\t\tDDD1F1461CD0832400EEC549 /* SDWebImageTableViewCell.m */,\n\t\t\t\tDDD1F1471CD0832400EEC549 /* TriditionTableViewCell.h */,\n\t\t\t\tDDD1F1481CD0832400EEC549 /* TriditionTableViewCell.m */,\n\t\t\t\tDDD1F19E1CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.h */,\n\t\t\t\tDDD1F19F1CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.m */,\n\t\t\t\tDDBECFCB1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.h */,\n\t\t\t\tDDBECFCC1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.m */,\n\t\t\t\tDD8E088C1D5DD5BD00FEBC3A /* ProgressImageView.h */,\n\t\t\t\tDD8E088D1D5DD5BD00FEBC3A /* ProgressImageView.m */,\n\t\t\t);\n\t\t\tpath = Cells;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDDD1F1571CD084E500EEC549 /* FlyImageIconView */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDDD1F15B1CD084E500EEC549 /* AppDelegate.h */,\n\t\t\t\tDDD1F15C1CD084E500EEC549 /* AppDelegate.m */,\n\t\t\t\tDDD1F1691CD084E500EEC549 /* Info.plist */,\n\t\t\t\tDDD1F1581CD084E500EEC549 /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = FlyImageIconView;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDDD1F1581CD084E500EEC549 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDDD1F1591CD084E500EEC549 /* main.m */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDDDEF42F1CE0AF4600C8366C /* SingleView */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDDDEF4331CE0AF4600C8366C /* AppDelegate.h */,\n\t\t\t\tDDDEF4341CE0AF4600C8366C /* AppDelegate.m */,\n\t\t\t\tDDDEF4361CE0AF4600C8366C /* SingleViewController.h */,\n\t\t\t\tDDDEF4371CE0AF4600C8366C /* SingleViewController.m */,\n\t\t\t\tDDDEF4411CE0AF4600C8366C /* Info.plist */,\n\t\t\t\tDDDEF4301CE0AF4600C8366C /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = SingleView;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDDDEF4301CE0AF4600C8366C /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDDDEF4311CE0AF4600C8366C /* main.m */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\tDD9D97421CC5044D008F279E /* FlyImageView */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = DD9D97651CC5044D008F279E /* Build configuration list for PBXNativeTarget \"FlyImageView\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t7BB62688892610CDF5BF155B /* [CP] Check Pods Manifest.lock */,\n\t\t\t\tDD9D973F1CC5044D008F279E /* Sources */,\n\t\t\t\tDD9D97401CC5044D008F279E /* Frameworks */,\n\t\t\t\tDD9D97411CC5044D008F279E /* Resources */,\n\t\t\t\tAF73610CB4A4FC61F7066FFF /* [CP] Embed Pods Frameworks */,\n\t\t\t\tFC8AB57C3D212803BBD51308 /* [CP] Copy Pods Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = FlyImageView;\n\t\t\tproductName = FlyImageView;\n\t\t\tproductReference = DD9D97431CC5044D008F279E /* FlyImageView.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\tDDBED1751CD8C5D600EC9263 /* WebP */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = DDBED1991CD8C5D600EC9263 /* Build configuration list for PBXNativeTarget \"WebP\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tF81A2E353A1692446C6C00E7 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\tDDBED1721CD8C5D600EC9263 /* Sources */,\n\t\t\t\tDDBED1731CD8C5D600EC9263 /* Frameworks */,\n\t\t\t\tDDBED1741CD8C5D600EC9263 /* Resources */,\n\t\t\t\tE33D266BAC01DC9109F97E25 /* [CP] Embed Pods Frameworks */,\n\t\t\t\tEC7C9F769F09EA99C51E707D /* [CP] Copy Pods Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = WebP;\n\t\t\tproductName = WebP;\n\t\t\tproductReference = DDBED1761CD8C5D600EC9263 /* WebP.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\tDDD1F1551CD084E500EEC549 /* FlyImageIconView */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = DDD1F1751CD084E500EEC549 /* Build configuration list for PBXNativeTarget \"FlyImageIconView\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t1DE98FA8A78C1C6538E9434F /* [CP] Check Pods Manifest.lock */,\n\t\t\t\tDDD1F1521CD084E500EEC549 /* Sources */,\n\t\t\t\tDDD1F1531CD084E500EEC549 /* Frameworks */,\n\t\t\t\tDDD1F1541CD084E500EEC549 /* Resources */,\n\t\t\t\tEC7C322CCF25D58E17ADE873 /* [CP] Embed Pods Frameworks */,\n\t\t\t\t3D1664DB16FAAE5424CC6B29 /* [CP] Copy Pods Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = FlyImageIconView;\n\t\t\tproductName = FlyImageIconView;\n\t\t\tproductReference = DDD1F1561CD084E500EEC549 /* FlyImageIconView.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\tDDDEF42D1CE0AF4600C8366C /* SingleView */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = DDDEF4441CE0AF4600C8366C /* Build configuration list for PBXNativeTarget \"SingleView\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t0A926CE0EFE2DD6A4B6420AC /* [CP] Check Pods Manifest.lock */,\n\t\t\t\tDDDEF42A1CE0AF4600C8366C /* Sources */,\n\t\t\t\tDDDEF42B1CE0AF4600C8366C /* Frameworks */,\n\t\t\t\tDDDEF42C1CE0AF4600C8366C /* Resources */,\n\t\t\t\tAA1CE48E20A4B22B24FDCBE0 /* [CP] Embed Pods Frameworks */,\n\t\t\t\t1FE7AD92C126F35569E2DA7F /* [CP] Copy Pods Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = SingleView;\n\t\t\tproductName = SingleView;\n\t\t\tproductReference = DDDEF42E1CE0AF4600C8366C /* SingleView.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tDD9D973B1CC5044D008F279E /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0830;\n\t\t\t\tORGANIZATIONNAME = Augmn;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\tDD9D97421CC5044D008F279E = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t};\n\t\t\t\t\tDDBED1751CD8C5D600EC9263 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t};\n\t\t\t\t\tDDD1F1551CD084E500EEC549 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t};\n\t\t\t\t\tDDDEF42D1CE0AF4600C8366C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = DD9D973E1CC5044D008F279E /* Build configuration list for PBXProject \"FlyImageView\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = DD9D973A1CC5044D008F279E;\n\t\t\tproductRefGroup = DD9D97441CC5044D008F279E /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tDD9D97421CC5044D008F279E /* FlyImageView */,\n\t\t\t\tDDD1F1551CD084E500EEC549 /* FlyImageIconView */,\n\t\t\t\tDDBED1751CD8C5D600EC9263 /* WebP */,\n\t\t\t\tDDDEF42D1CE0AF4600C8366C /* SingleView */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\tDD9D97411CC5044D008F279E /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDDD8FB601D59EB9200821392 /* Launch Screen.storyboard in Resources */,\n\t\t\t\tDDD1F1511CD083B300EEC549 /* Default-568h@2x.png in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDDBED1741CD8C5D600EC9263 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDDD8FB621D59EB9200821392 /* Launch Screen.storyboard in Resources */,\n\t\t\t\tDDBED1A11CD8C76700EC9263 /* Default-568h@2x.png in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDDD1F1541CD084E500EEC549 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDDD8FB611D59EB9200821392 /* Launch Screen.storyboard in Resources */,\n\t\t\t\tDDD1F1951CD08E7D00EEC549 /* Default-568h@2x.png in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDDDEF42C1CE0AF4600C8366C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDDD8FB631D59EB9200821392 /* Launch Screen.storyboard in Resources */,\n\t\t\t\tDDDEF4451CE0B8AA00C8366C /* Default-568h@2x.png in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t0A926CE0EFE2DD6A4B6420AC /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_ROOT}/../Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t1DE98FA8A78C1C6538E9434F /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_ROOT}/../Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t1FE7AD92C126F35569E2DA7F /* [CP] Copy Pods Resources */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Copy Pods Resources\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-SingleView/Pods-SingleView-resources.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t3D1664DB16FAAE5424CC6B29 /* [CP] Copy Pods Resources */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Copy Pods Resources\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-FlyImageIconView/Pods-FlyImageIconView-resources.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t7BB62688892610CDF5BF155B /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_ROOT}/../Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tAA1CE48E20A4B22B24FDCBE0 /* [CP] Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-SingleView/Pods-SingleView-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tAF73610CB4A4FC61F7066FFF /* [CP] Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-FlyImageView/Pods-FlyImageView-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tE33D266BAC01DC9109F97E25 /* [CP] Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-WebP/Pods-WebP-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tEC7C322CCF25D58E17ADE873 /* [CP] Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Embed Pods Frameworks\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-FlyImageIconView/Pods-FlyImageIconView-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tEC7C9F769F09EA99C51E707D /* [CP] Copy Pods Resources */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Copy Pods Resources\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-WebP/Pods-WebP-resources.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tF81A2E353A1692446C6C00E7 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_ROOT}/../Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\tFC8AB57C3D212803BBD51308 /* [CP] Copy Pods Resources */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Copy Pods Resources\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-FlyImageView/Pods-FlyImageView-resources.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\tDD9D973F1CC5044D008F279E /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDDD1F1491CD0832400EEC549 /* BaseTableViewCell.m in Sources */,\n\t\t\t\tDD8E088E1D5DD5BD00FEBC3A /* ProgressImageView.m in Sources */,\n\t\t\t\tDDD1F14E1CD0832400EEC549 /* SDWebImageTableViewCell.m in Sources */,\n\t\t\t\tDD9D974B1CC5044D008F279E /* AppDelegate.m in Sources */,\n\t\t\t\tDDD1F14F1CD0832400EEC549 /* TriditionTableViewCell.m in Sources */,\n\t\t\t\tDDD1F14D1CD0832400EEC549 /* FlyImageTableViewCell.m in Sources */,\n\t\t\t\tDDD1F14C1CD0832400EEC549 /* FlyImageLayerTableViewCell.m in Sources */,\n\t\t\t\tDD9D97481CC5044D008F279E /* main.m in Sources */,\n\t\t\t\tDDD1F1391CD0831F00EEC549 /* RootViewController.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDDBED1721CD8C5D600EC9263 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDD2EDB131D61E6C30085C9E3 /* ProgressImageView.m in Sources */,\n\t\t\t\tDDBED17D1CD8C5D600EC9263 /* AppDelegate.m in Sources */,\n\t\t\t\tDDBED19B1CD8C70C00EC9263 /* RootViewController.m in Sources */,\n\t\t\t\tDDBED19D1CD8C71900EC9263 /* TriditionTableViewCell.m in Sources */,\n\t\t\t\tDDBED19F1CD8C72A00EC9263 /* FlyImageTableViewCell.m in Sources */,\n\t\t\t\tDDBED19E1CD8C71B00EC9263 /* SDWebImageTableViewCell.m in Sources */,\n\t\t\t\tDDBED19C1CD8C71100EC9263 /* BaseTableViewCell.m in Sources */,\n\t\t\t\tDDBED1A01CD8C72E00EC9263 /* FlyImageLayerTableViewCell.m in Sources */,\n\t\t\t\tDDBED17A1CD8C5D600EC9263 /* main.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDDD1F1521CD084E500EEC549 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDDD1F1941CD08D1E00EEC549 /* RootViewController.m in Sources */,\n\t\t\t\tDDD1F18F1CD0872D00EEC549 /* BaseTableViewCell.m in Sources */,\n\t\t\t\tDDD1F1A01CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.m in Sources */,\n\t\t\t\tDDD1F1911CD0872D00EEC549 /* SDWebImageTableViewCell.m in Sources */,\n\t\t\t\tDDD1F1931CD0872D00EEC549 /* TriditionTableViewCell.m in Sources */,\n\t\t\t\tDDD1F15D1CD084E500EEC549 /* AppDelegate.m in Sources */,\n\t\t\t\tDDD1F15A1CD084E500EEC549 /* main.m in Sources */,\n\t\t\t\tDDBECFCD1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDDDEF42A1CE0AF4600C8366C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDDDEF4381CE0AF4600C8366C /* SingleViewController.m in Sources */,\n\t\t\t\tDDDEF4351CE0AF4600C8366C /* AppDelegate.m in Sources */,\n\t\t\t\tDDDEF4321CE0AF4600C8366C /* main.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\tDD9D97631CC5044D008F279E /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDD9D97641CC5044D008F279E /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDD9D97661CC5044D008F279E /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 841CA4D45E6400A9646A0F66 /* Pods-FlyImageView.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\tINFOPLIST_FILE = FlyImageView/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.augmn.test;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDD9D97671CC5044D008F279E /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 3ABB5A3F814E3BFC95A513BD /* Pods-FlyImageView.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\tINFOPLIST_FILE = FlyImageView/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.augmn.test;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDDBED1951CD8C5D600EC9263 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = D95E1058D32716446EB3DC84 /* Pods-WebP.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = WebP/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageview.WebP;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDDBED1961CD8C5D600EC9263 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = E8620E15B0D1F42DDE6C37AA /* Pods-WebP.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = WebP/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageview.WebP;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDDD1F1761CD084E500EEC549 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7D3083C3FEEB3316F9CCCF92 /* Pods-FlyImageIconView.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = FlyImageIconView/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageiconview;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDDD1F1771CD084E500EEC549 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 02F5D49EB862BEC96204662A /* Pods-FlyImageIconView.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = FlyImageIconView/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageiconview;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDDDEF4421CE0AF4600C8366C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = FF39DAB46C23D364F5631D94 /* Pods-SingleView.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = SingleView/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageview.SingleView;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDDDEF4431CE0AF4600C8366C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 33A4E8609F3283491E3DD133 /* Pods-SingleView.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = SingleView/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageview.SingleView;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\tDD9D973E1CC5044D008F279E /* Build configuration list for PBXProject \"FlyImageView\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDD9D97631CC5044D008F279E /* Debug */,\n\t\t\t\tDD9D97641CC5044D008F279E /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tDD9D97651CC5044D008F279E /* Build configuration list for PBXNativeTarget \"FlyImageView\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDD9D97661CC5044D008F279E /* Debug */,\n\t\t\t\tDD9D97671CC5044D008F279E /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tDDBED1991CD8C5D600EC9263 /* Build configuration list for PBXNativeTarget \"WebP\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDDBED1951CD8C5D600EC9263 /* Debug */,\n\t\t\t\tDDBED1961CD8C5D600EC9263 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tDDD1F1751CD084E500EEC549 /* Build configuration list for PBXNativeTarget \"FlyImageIconView\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDDD1F1761CD084E500EEC549 /* Debug */,\n\t\t\t\tDDD1F1771CD084E500EEC549 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tDDDEF4441CE0AF4600C8366C /* Build configuration list for PBXNativeTarget \"SingleView\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDDDEF4421CE0AF4600C8366C /* Debug */,\n\t\t\t\tDDDEF4431CE0AF4600C8366C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = DD9D973B1CC5044D008F279E /* Project object */;\n}\n"
  },
  {
    "path": "Examples/FlyImageView.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:FlyImageView.xcodeproj\">\n   </FileRef>\n   <FileRef\n      location = \"group:Pods/Pods.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/FlyImageIconView.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"DDD1F1551CD084E500EEC549\"\n               BuildableName = \"FlyImageIconView.app\"\n               BlueprintName = \"FlyImageIconView\"\n               ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DDD1F1551CD084E500EEC549\"\n            BuildableName = \"FlyImageIconView.app\"\n            BlueprintName = \"FlyImageIconView\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DDD1F1551CD084E500EEC549\"\n            BuildableName = \"FlyImageIconView.app\"\n            BlueprintName = \"FlyImageIconView\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DDD1F1551CD084E500EEC549\"\n            BuildableName = \"FlyImageIconView.app\"\n            BlueprintName = \"FlyImageIconView\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/FlyImageView.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"DD9D97421CC5044D008F279E\"\n               BuildableName = \"FlyImageView.app\"\n               BlueprintName = \"FlyImageView\"\n               ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DD9D97421CC5044D008F279E\"\n            BuildableName = \"FlyImageView.app\"\n            BlueprintName = \"FlyImageView\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DD9D97421CC5044D008F279E\"\n            BuildableName = \"FlyImageView.app\"\n            BlueprintName = \"FlyImageView\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DD9D97421CC5044D008F279E\"\n            BuildableName = \"FlyImageView.app\"\n            BlueprintName = \"FlyImageView\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/SingleView.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"DDDEF42D1CE0AF4600C8366C\"\n               BuildableName = \"SingleView.app\"\n               BlueprintName = \"SingleView\"\n               ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DDDEF42D1CE0AF4600C8366C\"\n            BuildableName = \"SingleView.app\"\n            BlueprintName = \"SingleView\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DDDEF42D1CE0AF4600C8366C\"\n            BuildableName = \"SingleView.app\"\n            BlueprintName = \"SingleView\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DDDEF42D1CE0AF4600C8366C\"\n            BuildableName = \"SingleView.app\"\n            BlueprintName = \"SingleView\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/WebP.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"DDBED1751CD8C5D600EC9263\"\n               BuildableName = \"WebP.app\"\n               BlueprintName = \"WebP\"\n               ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DDBED1751CD8C5D600EC9263\"\n            BuildableName = \"WebP.app\"\n            BlueprintName = \"WebP\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DDBED1751CD8C5D600EC9263\"\n            BuildableName = \"WebP.app\"\n            BlueprintName = \"WebP\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DDBED1751CD8C5D600EC9263\"\n            BuildableName = \"WebP.app\"\n            BlueprintName = \"WebP\"\n            ReferencedContainer = \"container:FlyImageView.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "Examples/Podfile",
    "content": "platform :ios, '8.0'\n\n# ignore all warnings from all pods\ninhibit_all_warnings!\n\ntarget 'FlyImageView' do\n\tpod 'SDWebImage', '~> 3.7'\n\tpod 'FlyImage', :path => '../FlyImage.podspec'\nend\n\ntarget 'FlyImageIconView' do\n\tpod 'SDWebImage', '~> 3.7'\n\tpod 'FlyImage', :path => '../FlyImage.podspec'\nend\n\ntarget 'WebP' do\n\tpod 'SDWebImage/WebP', '~> 3.7'\n\tpod 'FlyImage/WebP', :path => '../FlyImage.podspec'\nend\n\ntarget 'SingleView' do\n\tpod 'FlyImage', :path => '../FlyImage.podspec'\nend\n"
  },
  {
    "path": "Examples/SingleView/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  SingleView\n//\n//  Created by Ye Tong on 5/9/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n\n\n@end\n\n"
  },
  {
    "path": "Examples/SingleView/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  SingleView\n//\n//  Created by Ye Tong on 5/9/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n#import \"SingleViewController.h\"\n\n@interface AppDelegate ()\n\n@end\n\n@implementation AppDelegate\n\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n\t// Override point for customization after application launch.\n\tself.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n\tself.window.backgroundColor = [UIColor blackColor];\n\t\n\tSingleViewController *rootViewController = [[SingleViewController alloc] init];\n\tself.window.rootViewController = rootViewController;\n\t[self.window makeKeyAndVisible];\n\t\n\treturn YES;\n}\n\n- (void)applicationWillResignActive:(UIApplication *)application {\n\t// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.\n\t// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.\n}\n\n- (void)applicationDidEnterBackground:(UIApplication *)application {\n\t// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.\n\t// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.\n}\n\n- (void)applicationWillEnterForeground:(UIApplication *)application {\n\t// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.\n}\n\n- (void)applicationDidBecomeActive:(UIApplication *)application {\n\t// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.\n}\n\n- (void)applicationWillTerminate:(UIApplication *)application {\n\t// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.\n}\n\n@end\n"
  },
  {
    "path": "Examples/SingleView/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>UILaunchStoryboardName</key>\n\t<string>Launch Screen</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UIRequiresFullScreen</key>\n\t<true/>\n\t<key>UIStatusBarHidden</key>\n\t<false/>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Examples/SingleView/SingleViewController.h",
    "content": "//\n//  ViewController.h\n//  SingleView\n//\n//  Created by Ye Tong on 5/9/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface SingleViewController : UIViewController\n\n\n@end\n\n"
  },
  {
    "path": "Examples/SingleView/SingleViewController.m",
    "content": "//\n//  SingleViewController.m\n//  SingleView\n//\n//  Created by Ye Tong on 5/9/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import \"SingleViewController.h\"\n#import \"FlyImage.h\"\n\n@implementation SingleViewController {\n\tNSMutableArray *_imageViews;\n\tNSMutableArray *_iconViews;\n}\n\n- (BOOL)prefersStatusBarHidden {\n\treturn YES;\n}\n\n- (void)viewDidLoad {\n\t[super viewDidLoad];\n\t[FlyImageCache sharedInstance].autoDismissImage = YES;\n\t\n\t_imageViews = [NSMutableArray new];\n\t_iconViews = [NSMutableArray new];\n\t\n\t// add // remove // clear\n\tCGFloat fromY = self.view.bounds.size.height - 200;\n\t[self insertButtonWithTitle:@\"AddImageView\" selector:@selector(onAddImageView) point:CGPointMake(10, fromY)];\n\t[self insertButtonWithTitle:@\"RemoveImageView\" selector:@selector(onRemoveImageView) point:CGPointMake(self.view.bounds.size.width/2 - 40, fromY)];\n\t[self insertButtonWithTitle:@\"ClearImageViews\" selector:@selector(onClearImageViews) point:CGPointMake(self.view.bounds.size.width - 90, fromY)];\n\t\n\t[self insertButtonWithTitle:@\"AddIconView\" selector:@selector(onAddIconView) point:CGPointMake(10, fromY + 100)];\n\t[self insertButtonWithTitle:@\"RemoveIconView\" selector:@selector(onRemoveIconView) point:CGPointMake(self.view.bounds.size.width/2 - 40, fromY + 100)];\n\t[self insertButtonWithTitle:@\"ClearIconViews\" selector:@selector(onClearIconViews) point:CGPointMake(self.view.bounds.size.width - 90, fromY + 100)];\n\t\n}\n\n- (void)insertButtonWithTitle:(NSString *)title selector:(SEL)selector point:(CGPoint)point {\n\tUIButton *addButton = [UIButton buttonWithType:UIButtonTypeSystem];\n\taddButton.frame = CGRectMake(point.x, point.y, 80, 44);\n\taddButton.backgroundColor = [UIColor orangeColor];\n\t[addButton setTitle:title forState:UIControlStateNormal];\n\t[addButton addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside];\n\taddButton.titleLabel.adjustsFontSizeToFitWidth = YES;\n\t[self.view addSubview:addButton];\n}\n\n- (void)onAddImageView {\n\tstatic NSInteger kCount = 0;\n\t\n\tNSMutableArray *imagesInRow = [NSMutableArray new];\n\tCGFloat size = self.view.bounds.size.width / 5;\n\tNSInteger index = kCount % 100;\n\t\n\tfor (NSInteger i=0; i<4; i++) {\n\t\tUIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(i * (size + 10), [_imageViews count] * (size + 10), size, size)];\n\t\tNSURL *url = [NSURL URLWithString: [NSString stringWithFormat:@\"http://liuliantv.oss-cn-beijing.aliyuncs.com/flyimage/%ld.jpg\", (long)index]];\n\t\timageView.imageURL = url;\n\t\t[self.view insertSubview:imageView atIndex:0];\n\t\t\n\t\t[imagesInRow addObject:imageView];\n\t}\n\t\n\t[_imageViews addObject:imagesInRow];\n\tkCount++;\n}\n\n- (void)onRemoveImageView {\n\tNSArray *imagesInRow = [_imageViews lastObject];\n\tfor (UIImageView *imageView in imagesInRow) {\n\t\t[imageView removeFromSuperview];\n\t}\n\t\n\t[_imageViews removeLastObject];\n}\n\n- (void)onClearImageViews {\n\tfor (NSArray *imagesInRow in _imageViews) {\n\t\tfor (UIImageView *imageView in imagesInRow) {\n\t\t\t[imageView removeFromSuperview];\n\t\t}\n\t}\n\t\n\t[_imageViews removeAllObjects];\n}\n\n- (void)onAddIconView {\n\tstatic NSInteger kCount = 0;\n\t\n\tNSMutableArray *imagesInRow = [NSMutableArray new];\n\tCGFloat size = self.view.bounds.size.width / 5;\n\tNSInteger index = kCount % 100;\n\t\n\tfor (NSInteger i=0; i<4; i++) {\n\t\tUIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(i * (size + 10), [_iconViews count] * (size + 10), size, size)];\n\t\tNSURL *url = [NSURL URLWithString: [NSString stringWithFormat:@\"http://liuliantv.oss-cn-beijing.aliyuncs.com/flyimage/%ld_tn.jpg\", (long)index]];\n\t\timageView.iconURL = url;\n\t\t[self.view insertSubview:imageView atIndex:0];\n\t\t\n\t\t[imagesInRow addObject:imageView];\n\t}\n\t\n\t[_iconViews addObject:imagesInRow];\n\tkCount++;\n}\n\n- (void)onRemoveIconView {\n\tNSArray *imagesInRow = [_iconViews lastObject];\n\tfor (UIImageView *imageView in imagesInRow) {\n\t\t[imageView removeFromSuperview];\n\t}\n\t\n\t[_iconViews removeLastObject];\n}\n\n- (void)onClearIconViews {\n\tfor (NSArray *imagesInRow in _iconViews) {\n\t\tfor (UIImageView *imageView in imagesInRow) {\n\t\t\t[imageView removeFromSuperview];\n\t\t}\n\t}\n\t\n\t[_iconViews removeAllObjects];\n}\n\n@end\n"
  },
  {
    "path": "Examples/SingleView/main.m",
    "content": "//\n//  main.m\n//  SingleView\n//\n//  Created by Ye Tong on 5/9/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n\t@autoreleasepool {\n\t    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n\t}\n}\n"
  },
  {
    "path": "Examples/WebP/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  WebP\n//\n//  Created by Ye Tong on 5/3/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n\n\n@end\n\n"
  },
  {
    "path": "Examples/WebP/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  WebP\n//\n//  Created by Ye Tong on 5/3/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n#import \"RootViewController.h\"\n#import \"FlyImageTableViewCell.h\"\n#import \"FlyImageLayerTableViewCell.h\"\n#import \"SDWebImageTableViewCell.h\"\n#import \"FlyImage.h\"\n\n@interface AppDelegate ()\n\n@end\n\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n\n\tself.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n\tself.window.backgroundColor = [UIColor whiteColor];\n\t\n\t[FlyImageCache sharedInstance].autoDismissImage = YES;\n\t\n\tRootViewController *rootViewController = [[RootViewController alloc] init];\n\trootViewController.suffix = @\".webp\";\n\trootViewController.heightOfCell = 150;\n\trootViewController.cellsPerRow = 1;\n\trootViewController.cells = @[ @{\n\t\t\t\t\t\t\t\t\t  @\"class\": [SDWebImageTableViewCell class],\n\t\t\t\t\t\t\t\t\t  @\"title\": @\"SDWebImage\"\n\t\t\t\t\t\t\t\t\t  } ,@{\n\t\t\t\t\t\t\t\t\t  @\"class\": [FlyImageTableViewCell class],\n\t\t\t\t\t\t\t\t\t  @\"title\": @\"FlyImageView\"\n\t\t\t\t\t\t\t\t\t  } ,@{\n\t\t\t\t\t\t\t\t\t  @\"class\": [FlyImageLayerTableViewCell class],\n\t\t\t\t\t\t\t\t\t  @\"title\": @\"FlyImageLayer\"\n\t\t\t\t\t\t\t\t\t  }];\n\t\n\tself.window.rootViewController = rootViewController;\n\t[self.window makeKeyAndVisible];\n\t\n\treturn YES;\n}\n\n- (void)applicationWillResignActive:(UIApplication *)application {\n\t// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.\n\t// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.\n}\n\n- (void)applicationDidEnterBackground:(UIApplication *)application {\n\t// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.\n\t// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.\n}\n\n- (void)applicationWillEnterForeground:(UIApplication *)application {\n\t// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.\n}\n\n- (void)applicationDidBecomeActive:(UIApplication *)application {\n\t// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.\n}\n\n- (void)applicationWillTerminate:(UIApplication *)application {\n\t// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.\n}\n\n@end\n"
  },
  {
    "path": "Examples/WebP/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>UILaunchStoryboardName</key>\n\t<string>Launch Screen</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UIRequiresFullScreen</key>\n\t<true/>\n\t<key>UIStatusBarHidden</key>\n\t<false/>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Examples/WebP/main.m",
    "content": "//\n//  main.m\n//  WebP\n//\n//  Created by Ye Tong on 5/3/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n\t@autoreleasepool {\n\t    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n\t}\n}\n"
  },
  {
    "path": "FlyImage/Core/FlyImageCache.h",
    "content": "//\n//  FlyImageCache.h\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"FlyImageCacheProtocol.h\"\n@class FlyImageDataFileManager;\n\n/**\n *\tManage image files in one folder.\n */\n@interface FlyImageCache : NSObject <FlyImageCacheProtocol>\n\n@property (nonatomic, assign) CGFloat maxCachedBytes; // Default is 512Mb.\n@property (nonatomic, assign) BOOL autoDismissImage; // If you want to reduce memory when the app enter background, set this flag as YES. Default is NO.\n@property (nonatomic, strong) FlyImageDataFileManager* dataFileManager;\n\n#ifdef FLYIMAGE_WEBP\n@property (nonatomic, assign) BOOL autoConvertWebP; // Should convert WebP file to JPEG file automaticlly. Default is NO. If yes, it will speed up retrieving operation for the next time.\n@property (nonatomic, assign) CGFloat compressionQualityForWebP; // Default is 0.8.\n#endif\n\n- (void)addImageWithKey:(NSString*)key\n               filename:(NSString*)filename\n              completed:(FlyImageCacheRetrieveBlock)completed;\n\n- (void)addImageWithKey:(NSString*)key\n               filename:(NSString*)filename\n               drawSize:(CGSize)drawSize\n        contentsGravity:(NSString* const)contentsGravity\n           cornerRadius:(CGFloat)cornerRadius\n              completed:(FlyImageCacheRetrieveBlock)completed;\n\n/**\n *  Get image with customize parameters from cache asynchronously.\n *  Avoid executing `CGDataProviderCreateWithCopyOfData`.\n *\n *  @param key             image key\n *  @param drawSize        render size\n *  @param contentsGravity contentMode of render view\n *  @param cornerRadius    cornerRadius of render view\n *  @param completed       callback\n */\n- (void)asyncGetImageWithKey:(NSString*)key\n                    drawSize:(CGSize)drawSize\n             contentsGravity:(NSString* const)contentsGravity\n                cornerRadius:(CGFloat)cornerRadius\n                   completed:(FlyImageCacheRetrieveBlock)completed;\n\n/**\n *  Get the image path saved in the disk.\n */\n- (NSString*)imagePathWithKey:(NSString*)key;\n\n/**\n *  Protect the file, which can't be removed.\n *\n *  @param key image key\n */\n- (void)protectFileWithKey:(NSString*)key;\n\n/**\n *  Don't protect the file, which can be removed.\n *\n *  @param key image key\n */\n- (void)unProtectFileWithKey:(NSString*)key;\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageCache.m",
    "content": "//\n//  FlyImageCache.m\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"FlyImageCache.h\"\n#import \"FlyImageDataFileManager.h\"\n#import \"FlyImageUtils.h\"\n#import \"FlyImageDecoder.h\"\n#import \"FlyImageRetrieveOperation.h\"\n\n#define kImageInfoIndexFileName 0\n#define kImageInfoIndexContentType 1\n#define kImageInfoIndexWidth 2\n#define kImageInfoIndexHeight 3\n#define kImageInfoIndexLock 4\n\n@interface FlyImageCache ()\n@property (nonatomic, strong) FlyImageDecoder* decoder;\n@end\n\n@implementation FlyImageCache {\n    NSRecursiveLock* _lock;\n    NSString* _metaPath;\n    NSMutableDictionary* _images;\n    NSMutableDictionary* _addingImages;\n    NSOperationQueue* _retrievingQueue;\n}\n\n+ (instancetype)sharedInstance\n{\n    static dispatch_once_t onceToken;\n    static FlyImageCache* __instance = nil;\n    dispatch_once(&onceToken, ^{\n\t\tNSString *metaPath = [[FlyImageUtils directoryPath] stringByAppendingPathComponent:@\"/__images\"];\n\t\t__instance = [[[self class] alloc] initWithMetaPath:metaPath];\n    });\n\n    return __instance;\n}\n\n- (instancetype)initWithMetaPath:(NSString*)metaPath\n{\n    if (self = [self init]) {\n        _lock = [[NSRecursiveLock alloc] init];\n        _addingImages = [[NSMutableDictionary alloc] init];\n        _maxCachedBytes = 1024 * 1024 * 512;\n        _retrievingQueue = [NSOperationQueue new];\n        _retrievingQueue.qualityOfService = NSQualityOfServiceUserInteractive;\n        _retrievingQueue.maxConcurrentOperationCount = 6;\n\n#ifdef FLYIMAGE_WEBP\n        _autoConvertWebP = NO;\n        _compressionQualityForWebP = 0.8;\n#endif\n\n        _metaPath = [metaPath copy];\n        NSString* folderPath = [[_metaPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@\"/files\"];\n        self.dataFileManager = [[FlyImageDataFileManager alloc] initWithFolderPath:folderPath];\n\n        _metaPath = [metaPath copy];\n        [self loadMetadata];\n\n        _decoder = [[FlyImageDecoder alloc] init];\n\n        [[NSNotificationCenter defaultCenter] addObserver:self\n                                                 selector:@selector(onWillTerminate)\n                                                     name:UIApplicationWillTerminateNotification\n                                                   object:nil];\n\n        [[NSNotificationCenter defaultCenter] addObserver:self\n                                                 selector:@selector(onDidEnterBackground)\n                                                     name:UIApplicationDidEnterBackgroundNotification\n                                                   object:nil];\n    }\n    return self;\n}\n\n#pragma mark - LifeCircle\n\n- (void)dealloc\n{\n    [_retrievingQueue cancelAllOperations];\n\n    [self cleanCachedImages];\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\n}\n\n- (void)onWillTerminate\n{\n    [self cleanCachedImages];\n}\n\n- (void)onDidEnterBackground\n{\n    [self cleanCachedImages];\n}\n\n- (void)cleanCachedImages\n{\n    [_retrievingQueue cancelAllOperations];\n\n    __weak __typeof__(self) weakSelf = self;\n    [self.dataFileManager calculateSizeWithCompletionBlock:^(NSUInteger fileCount, NSUInteger totalSize) {\n\t\tif ( weakSelf.maxCachedBytes > totalSize ) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tNSMutableArray *lockedFilenames = [NSMutableArray array];\n\t\tNSMutableArray *lockedKeys = [NSMutableArray array];\n\t\t@synchronized (_images) {\n\t\t\tfor (NSString *key in _images) {\n\t\t\t\tNSArray *imageInfo = [_images objectForKey:key];\n\t\t\t\tif ( [imageInfo count] > kImageInfoIndexLock && [[imageInfo objectAtIndex:kImageInfoIndexLock] boolValue] ){\n\t\t\t\t\t[lockedFilenames addObject:[imageInfo objectAtIndex:kImageInfoIndexFileName]];\n\t\t\t\t\t[lockedKeys addObject:key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\t[weakSelf.dataFileManager purgeWithExceptions:lockedFilenames\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   toSize:weakSelf.maxCachedBytes/2\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcompleted:^(NSUInteger fileCount, NSUInteger totalSize) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// remove unlock keys\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t@synchronized (_images) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNSArray *allKeys = [_images allKeys];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfor (NSString *key in allKeys) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( [lockedKeys indexOfObject:key] == NSNotFound ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t[_images removeObjectForKey:key];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t[weakSelf saveMetadata];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}];\n    }];\n}\n\n#pragma mark - APIs\n- (void)addImageWithKey:(NSString*)key\n               filename:(NSString*)filename\n              completed:(FlyImageCacheRetrieveBlock)completed\n{\n    [self addImageWithKey:key filename:filename drawSize:CGSizeZero contentsGravity:kCAGravityResizeAspect cornerRadius:0 completed:completed];\n}\n\n- (void)addImageWithKey:(NSString*)key\n               filename:(NSString*)filename\n               drawSize:(CGSize)drawSize\n        contentsGravity:(NSString* const)contentsGravity\n           cornerRadius:(CGFloat)cornerRadius\n              completed:(FlyImageCacheRetrieveBlock)completed\n{\n\n    NSParameterAssert(key != nil);\n    NSParameterAssert(filename != nil);\n\n    if ([self isImageExistWithKey:key] && completed != nil) {\n        [self asyncGetImageWithKey:key\n                          drawSize:drawSize\n                   contentsGravity:contentsGravity\n                      cornerRadius:cornerRadius\n                         completed:completed];\n        return;\n    }\n\n    // ignore draw size when add images\n    @synchronized(_addingImages)\n    {\n        if ([_addingImages objectForKey:key] == nil) {\n            NSMutableArray* blocks = [NSMutableArray array];\n            if (completed != nil) {\n                [blocks addObject:completed];\n            }\n\n            [_addingImages setObject:blocks forKey:key];\n        } else {\n            // waiting for drawing\n            NSMutableArray* blocks = [_addingImages objectForKey:key];\n            if (completed != nil) {\n                [blocks addObject:completed];\n            }\n\n            return;\n        }\n    }\n\n    [self doAddImageWithKey:[key copy]\n                   filename:[filename copy]\n                   drawSize:drawSize\n            contentsGravity:contentsGravity\n               cornerRadius:cornerRadius\n                  completed:completed];\n}\n\n- (void)doAddImageWithKey:(NSString*)key\n                 filename:(NSString*)filename\n                 drawSize:(CGSize)drawSize\n          contentsGravity:(NSString* const)contentsGravity\n             cornerRadius:(CGFloat)cornerRadius\n                completed:(FlyImageCacheRetrieveBlock)completed\n{\n\n    static dispatch_queue_t __drawingQueue = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n\t\tNSString *name = [NSString stringWithFormat:@\"com.flyimage.addimage.%@\", [[NSUUID UUID] UUIDString]];\n\t\t__drawingQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], NULL);\n    });\n\n    dispatch_async(__drawingQueue, ^{\n\t\t\n\t\t// get image meta\n\t\tCGSize imageSize = CGSizeZero;\n\t\tImageContentType contentType;\n\t\t@autoreleasepool {\n\t\t\tNSString *filePath = [self.dataFileManager.folderPath stringByAppendingPathComponent:filename];\n\t\t\tNSData *fileData = [NSData dataWithContentsOfFile:filePath];\n\t\t\tcontentType = [FlyImageUtils contentTypeForImageData:fileData];\n\t\t\tUIImage *image = nil;\n\t\t\tif ( contentType == ImageContentTypeWebP ) {\n#ifdef FLYIMAGE_WEBP\n\t\t\t\tif ( _autoConvertWebP ) {\n\t\t\t\t\t// Decode WebP\n\t\t\t\t\tBOOL hasAlpha;\n\t\t\t\t\timage = [_decoder imageWithWebPData:fileData hasAlpha:&hasAlpha];\n\t\t\t\t\tif ( image != nil ) {\n\t\t\t\t\t\tNSData *compresstionImageData;\n\t\t\t\t\t\tif ( hasAlpha ) {\n\t\t\t\t\t\t\t// Convert WebP to PNG\n\t\t\t\t\t\t\tcompresstionImageData = UIImagePNGRepresentation(image);\n\t\t\t\t\t\t\tif ( compresstionImageData != nil ){\n\t\t\t\t\t\t\t\tcontentType = ImageContentTypePNG;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t// Convert WebP to JPEG\n\t\t\t\t\t\t\tcompresstionImageData = UIImageJPEGRepresentation(image, self.compressionQualityForWebP);\n\t\t\t\t\t\t\tif ( compresstionImageData != nil ){\n\t\t\t\t\t\t\t\tcontentType = ImageContentTypeJPEG;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// save image into disk\n\t\t\t\t\t\tif ( compresstionImageData != nil ){\n\t\t\t\t\t\t\tNSString *filePath = [self.dataFileManager.folderPath stringByAppendingPathComponent:filename];\n\t\t\t\t\t\t\t[compresstionImageData writeToFile:filePath atomically:YES];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n#endif\n\t\t\t}else{\n\t\t\t\t// read image meta, not data\n\t\t\t\timage = [UIImage imageWithData:fileData];\n\t\t\t}\n\t\t\t\n\t\t\timageSize = image.size;\n\t\t}\n\t\t\n\t\t[self.dataFileManager addExistFileName:filename];\n\t\tFlyImageDataFile *dataFile = [self.dataFileManager retrieveFileWithName:filename];\n\t\tif ( [dataFile open] == false ) {\n\t\t\t[self afterAddImage:nil key:key];\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// save data file's param\n\t\tvoid *bytes = dataFile.address;\n\t\tsize_t fileLength = (size_t)dataFile.fileLength;\n\t\t\n\t\t// callback with image\n\t\tUIImage *decodeImage = [_decoder imageWithFile:(__bridge void *)(dataFile)\n                                             contentType:contentType\n                                                   bytes:bytes\n                                                  length:fileLength\n                                                drawSize:CGSizeEqualToSize(drawSize, CGSizeZero) ? imageSize : drawSize\n                                         contentsGravity:contentsGravity\n                                            cornerRadius:cornerRadius];\n\t\t[self afterAddImage:decodeImage key:key];\n\t\t\n\t\t@synchronized (_images) {\n\t\t\t// path, width, height, length\n\t\t\tNSArray *imageInfo = @[ filename,\n\t\t\t\t\t\t\t\t\t@(contentType),\n\t\t\t\t\t\t\t\t\t@(imageSize.width),\n\t\t\t\t\t\t\t\t\t@(imageSize.height) ];\n\t\t\t\n\t\t\t[_images setObject:imageInfo forKey:key];\n\t\t}\n\t\t\n\t\t// save meta\n\t\t[self saveMetadata];\n    });\n}\n\n- (void)afterAddImage:(UIImage*)image key:(NSString*)key\n{\n    NSArray* blocks = nil;\n    @synchronized(_addingImages)\n    {\n        blocks = [[_addingImages objectForKey:key] copy];\n        [_addingImages removeObjectForKey:key];\n    }\n\n    dispatch_main_sync_safe(^{\n        for ( FlyImageCacheRetrieveBlock block in blocks) {\n            block( key, image );\n        }\n    });\n}\n\n- (void)removeImageWithKey:(NSString*)key\n{\n    NSString* fileName = nil;\n    @synchronized(_images)\n    {\n\n        NSArray* imageInfo = [_images objectForKey:key];\n        if (imageInfo == nil) {\n            return;\n        }\n\n        // if locked\n        if ([imageInfo count] > kImageInfoIndexLock && [[imageInfo objectAtIndex:kImageInfoIndexLock] boolValue] == YES) {\n            return;\n        }\n\n        [_images removeObjectForKey:key];\n\n        fileName = [imageInfo firstObject];\n    }\n\n    if (fileName != nil) {\n        [self.dataFileManager removeFileWithName:fileName];\n    }\n}\n\n- (void)changeImageKey:(NSString*)oldKey newKey:(NSString*)newKey\n{\n    @synchronized(_images)\n    {\n        id imageInfo = [_images objectForKey:oldKey];\n        if (imageInfo == nil) {\n            return;\n        }\n\n        [_images setObject:imageInfo forKey:newKey];\n        [_images removeObjectForKey:oldKey];\n    }\n}\n\n- (BOOL)isImageExistWithKey:(NSString*)key\n{\n    NSParameterAssert(key != nil);\n\n    @synchronized(_images)\n    {\n        return [_images objectForKey:key] != nil;\n    }\n}\n\n- (void)asyncGetImageWithKey:(NSString*)key completed:(FlyImageCacheRetrieveBlock)completed\n{\n    [self asyncGetImageWithKey:key drawSize:CGSizeZero contentsGravity:kCAGravityResizeAspect cornerRadius:0 completed:completed];\n}\n\n- (void)asyncGetImageWithKey:(NSString*)key\n                    drawSize:(CGSize)drawSize\n             contentsGravity:(NSString* const)contentsGravity\n                cornerRadius:(CGFloat)cornerRadius\n                   completed:(FlyImageCacheRetrieveBlock)completed\n{\n    NSParameterAssert(key != nil);\n    NSParameterAssert(completed != nil);\n\n    NSArray* imageInfo;\n    @synchronized(_images)\n    {\n        imageInfo = [_images objectForKey:key];\n    }\n\n    if (imageInfo == nil || [imageInfo count] <= kImageInfoIndexHeight) {\n        completed(key, nil);\n        return;\n    }\n\n    // filename, width, height, length\n    NSString* filename = [imageInfo firstObject];\n    FlyImageDataFile* dataFile = [self.dataFileManager retrieveFileWithName:filename];\n    if (dataFile == nil) {\n        completed(key, nil);\n        return;\n    }\n\n    // if the image is retrieving, then just add the block, no need to create a new operation.\n    for (FlyImageRetrieveOperation* operation in _retrievingQueue.operations) {\n        if ([operation.name isEqualToString:key]) {\n            [operation addBlock:completed];\n            return;\n        }\n    }\n\n    CGSize imageSize = drawSize;\n    if (drawSize.width == 0 && drawSize.height == 0) {\n        CGFloat imageWidth = [[imageInfo objectAtIndex:kImageInfoIndexWidth] floatValue];\n        CGFloat imageHeight = [[imageInfo objectAtIndex:kImageInfoIndexHeight] floatValue];\n        imageSize = CGSizeMake(imageWidth, imageHeight);\n    }\n    ImageContentType contentType = [[imageInfo objectAtIndex:kImageInfoIndexContentType] integerValue];\n\n    __weak __typeof__(self) weakSelf = self;\n    FlyImageRetrieveOperation* operation = [[FlyImageRetrieveOperation alloc] initWithRetrieveBlock:^UIImage * {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t if ( ![dataFile open] ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t return nil;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t return [weakSelf.decoder imageWithFile:(__bridge void *)(dataFile)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  contentType:contentType\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbytes:dataFile.address\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   length:(size_t)dataFile.fileLength\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t drawSize:CGSizeEqualToSize(drawSize, CGSizeZero) ? imageSize : drawSize\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  contentsGravity:contentsGravity\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t cornerRadius:cornerRadius];\n    }];\n    operation.name = key;\n    [operation addBlock:completed];\n    [_retrievingQueue addOperation:operation];\n}\n\n- (void)cancelGetImageWithKey:(NSString*)key\n{\n    NSParameterAssert(key != nil);\n\n    for (FlyImageRetrieveOperation* operation in _retrievingQueue.operations) {\n        if (!operation.cancelled && !operation.finished && [operation.name isEqualToString:key]) {\n            [operation cancel];\n            return;\n        }\n    }\n}\n\n- (void)purge\n{\n\n    NSMutableArray* lockedFilenames = [NSMutableArray array];\n    @synchronized(_images)\n    {\n        NSMutableArray* lockedKeys = [NSMutableArray array];\n        for (NSString* key in _images) {\n            NSArray* imageInfo = [_images objectForKey:key];\n            if ([imageInfo count] > kImageInfoIndexLock && [[imageInfo objectAtIndex:kImageInfoIndexLock] boolValue]) {\n                [lockedFilenames addObject:[imageInfo objectAtIndex:kImageInfoIndexFileName]];\n                [lockedKeys addObject:key];\n            }\n        }\n\n        // remove unlock keys\n        NSArray* allKeys = [_images allKeys];\n        for (NSString* key in allKeys) {\n            if ([lockedKeys indexOfObject:key] == NSNotFound) {\n                [_images removeObjectForKey:key];\n            }\n        }\n    }\n\n    [_retrievingQueue cancelAllOperations];\n\n    @synchronized(_addingImages)\n    {\n        for (NSString* key in _addingImages) {\n            NSArray* blocks = [_addingImages objectForKey:key];\n            dispatch_main_sync_safe(^{\n                for ( FlyImageCacheRetrieveBlock block in blocks) {\n                    block( key, nil );\n                }\n            });\n        }\n\n        [_addingImages removeAllObjects];\n    }\n\n    // remove files\n    [self.dataFileManager purgeWithExceptions:lockedFilenames toSize:0 completed:nil];\n\n    [self saveMetadata];\n}\n\n- (NSString*)imagePathWithKey:(NSString*)key\n{\n    NSParameterAssert(key != nil);\n\n    @synchronized(_images)\n    {\n        NSArray* fileInfo = [_images objectForKey:key];\n        if ([fileInfo firstObject] == nil) {\n            return nil;\n        }\n\n        NSString* filename = [fileInfo objectAtIndex:kImageInfoIndexFileName];\n        return [self.dataFileManager.folderPath stringByAppendingPathComponent:filename];\n    }\n}\n\n// 锁住文件，不能被回收\n- (void)protectFileWithKey:(NSString*)key\n{\n    NSParameterAssert(key != nil);\n\n    if (![self isImageExistWithKey:key]) {\n        return;\n    }\n\n    @synchronized(_images)\n    {\n        NSArray* fileInfo = [_images objectForKey:key];\n        if ([fileInfo firstObject] == nil) {\n            return;\n        }\n\n        // alread locked\n        if ([fileInfo count] > kImageInfoIndexLock && [[fileInfo objectAtIndex:kImageInfoIndexLock] boolValue]) {\n            return;\n        }\n\n        // name, type, width, height, lock\n        NSMutableArray* newFileInfo = [NSMutableArray arrayWithArray:[fileInfo subarrayWithRange:NSMakeRange(0, kImageInfoIndexLock)]];\n        [newFileInfo addObject:@(1)];\n        [_images setObject:newFileInfo forKey:key];\n\n        [self saveMetadata];\n    }\n}\n\n// 解锁文件，可以被回收\n- (void)unProtectFileWithKey:(NSString*)key\n{\n    NSParameterAssert(key != nil);\n\n    if (![self isImageExistWithKey:key]) {\n        return;\n    }\n\n    @synchronized(_images)\n    {\n        NSArray* fileInfo = [_images objectForKey:key];\n        if ([fileInfo firstObject] == nil) {\n            return;\n        }\n\n        // alread unlocked\n        if ([fileInfo count] <= kImageInfoIndexLock) {\n            return;\n        }\n\n        // name, type, width, height\n        NSArray* newFileInfo = [fileInfo subarrayWithRange:NSMakeRange(0, kImageInfoIndexLock)];\n        [_images setObject:newFileInfo forKey:key];\n\n        [self saveMetadata];\n    }\n}\n\n#pragma mark - Working with Metadata\n- (void)saveMetadata\n{\n    static dispatch_queue_t __metadataQueue = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n\t\tNSString *name = [NSString stringWithFormat:@\"com.flyimage.imagemeta.%@\", [[NSUUID UUID] UUIDString]];\n\t\t__metadataQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], NULL);\n    });\n\n    dispatch_async(__metadataQueue, ^{\n\t\t[_lock lock];\n\t\t\n\t\tNSData *data = [NSJSONSerialization dataWithJSONObject:[_images copy] options:kNilOptions error:NULL];\n\t\tBOOL fileWriteResult = [data writeToFile:_metaPath atomically:NO];\n\t\tif (fileWriteResult == NO) {\n\t\t\tFlyImageErrorLog(@\"couldn't save metadata\");\n\t\t}\n\t\t\n\t\t[_lock unlock];\n    });\n}\n\n- (void)loadMetadata\n{\n    // load content from index file\n    NSError* error;\n    NSData* metadataData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:_metaPath] options:NSDataReadingMappedAlways error:&error];\n    if (error != nil || metadataData == nil) {\n        [self createMetadata];\n        return;\n    }\n\n    NSDictionary* parsedObject = (NSDictionary*)[NSJSONSerialization JSONObjectWithData:metadataData options:kNilOptions error:&error];\n    if (error != nil || parsedObject == nil) {\n        [self createMetadata];\n        return;\n    }\n\n    _images = [NSMutableDictionary dictionaryWithDictionary:parsedObject];\n}\n\n- (void)createMetadata\n{\n    _images = [NSMutableDictionary dictionaryWithCapacity:100];\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageCacheProtocol.h",
    "content": "//\n//  FlyImageCacheProtocol.h\n//  Demo\n//\n//  Created by Norris Tong on 4/2/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#ifndef FlyImageCacheProtocol_h\n#define FlyImageCacheProtocol_h\n\ntypedef void (^FlyImageCacheRetrieveBlock)(NSString* key, UIImage* image);\n\n/**\n *  Common API for FlyImageCache and FlyImageIconCache.\n */\n@protocol FlyImageCacheProtocol <NSObject>\n\n/**\n *  Create an image cache with default meta path.\n */\n+ (instancetype)sharedInstance;\n\n/**\n *  Create an image cache with a specific meta path.\n *\n *  @param metaPath specific meta path, all the images will be saved into folder `metaPath/files`\n */\n- (instancetype)initWithMetaPath:(NSString*)metaPath;\n\n/**\n *  Get image from cache asynchronously.\n */\n- (void)asyncGetImageWithKey:(NSString*)key\n                   completed:(FlyImageCacheRetrieveBlock)completed;\n\n/**\n *  Cancel geting an image from cache if the image has not already got.\n */\n- (void)cancelGetImageWithKey:(NSString*)key;\n\n/**\n *  Check if image exists in cache synchronized. NO delay.\n */\n- (BOOL)isImageExistWithKey:(NSString*)key;\n\n/**\n *  Remove an image from cache.\n */\n- (void)removeImageWithKey:(NSString*)key;\n\n/**\n *  Change the old key with a new key\n */\n- (void)changeImageKey:(NSString*)oldKey\n                newKey:(NSString*)newKey;\n\n/**\n *  Remove all the images from the cache.\n */\n- (void)purge;\n\n@end\n\n#endif /* FlyImageCacheProtocol_h */\n"
  },
  {
    "path": "FlyImage/Core/FlyImageDataFile.h",
    "content": "//\n//  FlyImageDataFile.h\n//  Demo\n//\n//  Created by Ye Tong on 3/18/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n/**\n *  Wrapper of data file, map the disk file to the memory.\n *\n *  Only support `append` operation, we can move the pointer to replace the data.\n *\n */\n@interface FlyImageDataFile : NSObject\n\n@property (nonatomic, assign, readonly) void* address;\n@property (nonatomic, assign, readonly) off_t fileLength; // total length of the file.\n@property (nonatomic, assign, readonly) off_t pointer; // append the data after the pointer. Default is 0.\n@property (nonatomic, assign) size_t step; // Change the step value to increase the file length. Deafult is 1 byte.\n\n- (instancetype)initWithPath:(NSString*)path;\n\n- (BOOL)open;\n\n- (void)close;\n\n/**\n *  Check the file length, if it is not big enough, then increase the file length with step.\n *\n *  @param offset start position\n *  @param length data length\n *\n *  @return success or failed\n */\n- (BOOL)prepareAppendDataWithOffset:(size_t)offset length:(size_t)length;\n\n/**\n *  Append the data after pointer.\n *\n *  Must execute `prepareAppendDataWithOffset:length` first.\n *\n *  @param offset start position\n *  @param length data length\n *\n *  @return success or failed\n */\n- (BOOL)appendDataWithOffset:(size_t)offset length:(size_t)length;\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageDataFile.m",
    "content": "//\n//  FlyImageDataFile.m\n//  Demo\n//\n//  Created by Ye Tong on 3/18/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"FlyImageDataFile.h\"\n#import \"FlyImageCache.h\"\n#import \"FlyImageUtils.h\"\n#import <sys/mman.h>\n\n@implementation FlyImageDataFile {\n    NSString* _filePath;\n    int _fileDescriptor;\n    size_t _maxLength; // default is 100Mb.\n\n    NSRecursiveLock* _lock;\n}\n\n- (instancetype)initWithPath:(NSString*)path\n{\n    if (self = [self init]) {\n        _filePath = [path copy];\n        _maxLength = 1024 * 1024 * 100;\n        _step = 1;\n        _pointer = 0;\n        _lock = [[NSRecursiveLock alloc] init];\n        _fileDescriptor = -1;\n    }\n    return self;\n}\n\n- (void)dealloc\n{\n    // should close the file if it's not be used again.\n    [self close];\n}\n\n- (BOOL)open\n{\n    _fileDescriptor = open([_filePath fileSystemRepresentation], O_RDWR | O_CREAT, 0666);\n    if (_fileDescriptor < 0) {\n        FlyImageErrorLog(@\"can't file at %@\", _filePath);\n        return NO;\n    }\n\n    _fileLength = lseek(_fileDescriptor, 0, SEEK_END);\n    if (_fileLength == 0) {\n        [self increaseFileLength:_step];\n    } else {\n        [self mmap];\n    }\n\n    return YES;\n}\n\n- (void)close\n{\n    if (_fileDescriptor < 0) {\n        return;\n    }\n\n    [_lock lock];\n\n    close(_fileDescriptor);\n    _fileDescriptor = -1;\n\n    // 取消内存映射\n    [self munmap];\n\n    [_lock unlock];\n}\n\n- (void)munmap\n{\n    if (_address == NULL) {\n        return;\n    }\n\n    munmap(_address, (size_t)_fileLength);\n    _address = NULL;\n}\n\n- (void)mmap\n{\n    _address = mmap(NULL, (size_t)_fileLength, (PROT_READ | PROT_WRITE), (MAP_FILE | MAP_SHARED), _fileDescriptor, 0);\n}\n\n- (BOOL)prepareAppendDataWithOffset:(size_t)offset length:(size_t)length\n{\n    NSAssert(_fileDescriptor > -1, @\"open this file first.\");\n\n    [_lock lock];\n\n    // can't exceed maxLength\n    if (offset + length > _maxLength) {\n        [_lock unlock];\n        return NO;\n    }\n\n    // Check the file length, if it is not big enough, then increase the file length with step.\n    if (offset + length > _fileLength) {\n        size_t correctLength = ceill((length * 1.0 / _step)) * _step;\n        if (![self increaseFileLength:correctLength]) {\n            [_lock unlock];\n            return NO;\n        }\n    }\n\n    [_lock unlock];\n    return YES;\n}\n\n- (BOOL)appendDataWithOffset:(size_t)offset length:(size_t)length\n{\n    NSAssert(_fileDescriptor > -1, @\"open this file first.\");\n\n    [_lock lock];\n\n    int result = msync(_address + offset, length, MS_SYNC);\n    if (result < 0) {\n        FlyImageErrorLog(@\"append data failed\");\n        [_lock unlock];\n        return NO;\n    }\n\n    // move the pointer\n    if (offset + length > _pointer) {\n        _pointer = offset + length;\n    }\n\n    [_lock unlock];\n\n    return YES;\n}\n\n- (BOOL)increaseFileLength:(size_t)length\n{\n    [_lock lock];\n\n    // cancel map first\n    [self munmap];\n\n    // change file length\n    int result = ftruncate(_fileDescriptor, _fileLength + length);\n    if (result < 0) {\n        FlyImageErrorLog(@\"can't truncate data file\");\n        [_lock unlock];\n        return NO;\n    }\n\n    // remap\n    _fileLength = lseek(_fileDescriptor, 0, SEEK_END);\n    [self mmap];\n\n    [_lock unlock];\n\n    return YES;\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageDataFileManager.h",
    "content": "//\n//  FlyImageDataFileManager.h\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"FlyImageDataFile.h\"\n\n/**\n *  Manager of FlyImageDataFile. In charge of creating and deleting data file.\n */\n@interface FlyImageDataFileManager : NSObject\n\n@property (nonatomic, strong, readonly) NSString* folderPath; // folder saved data files.\n@property (nonatomic, assign, readonly) BOOL isDiskFull; // Default is NO.\n\n- (instancetype)initWithFolderPath:(NSString*)folderPath;\n\n/**\n *  Create a `FlyImageDataFile` if it doesn't exist.\n */\n- (FlyImageDataFile*)createFileWithName:(NSString*)name;\n\n/**\n *  Add an exist file.\n */\n- (void)addExistFileName:(NSString*)name;\n\n/**\n *  Check the file whether exist or not, no delay.\n */\n- (BOOL)isFileExistWithName:(NSString*)name;\n\n/**\n *  Get a `FlyImageDataFile` if it exists.\n */\n- (FlyImageDataFile*)retrieveFileWithName:(NSString*)name;\n\n/**\n *  Remove data file\n */\n- (void)removeFileWithName:(NSString*)name;\n\n/**\n *  Create a `FlyImageDataFile` async.\n */\n- (void)asyncCreateFileWithName:(NSString*)name completed:(void (^)(FlyImageDataFile* dataFile))completed;\n\n/**\n *  Remove all the data files, except some special files.\n *\n *  @param names     except files' names\n *  @param toSize    expected size of the folder\n *  @param completed callback\n */\n- (void)purgeWithExceptions:(NSArray*)names\n                     toSize:(NSUInteger)toSize\n                  completed:(void (^)(NSUInteger fileCount, NSUInteger totalSize))completed;\n\n/**\n *  Calculate the folder size.\n */\n- (void)calculateSizeWithCompletionBlock:(void (^)(NSUInteger fileCount, NSUInteger totalSize))block;\n\n/**\n *  Free space left in the system space.\n */\n- (void)freeDiskSpaceWithCompletionBlock:(void (^)(NSUInteger freeSize))block;\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageDataFileManager.m",
    "content": "//\n//  FlyImageDataFileManager.m\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"FlyImageDataFileManager.h\"\n#import \"FlyImageUtils.h\"\n\n@implementation FlyImageDataFileManager {\n    NSFileManager* _fileManager;\n    dispatch_queue_t _fileQueue;\n    NSMutableDictionary* _fileNames;\n    NSMutableDictionary* _creatingFiles;\n}\n\n- (instancetype)initWithFolderPath:(NSString*)folderPath\n{\n    if (self = [self init]) {\n        _folderPath = [folderPath copy];\n\n        // create a unique queue\n        NSString* queueName = [@\"com.flyimage.filemanager.\" stringByAppendingString:[[NSUUID UUID] UUIDString]];\n        _fileQueue = dispatch_queue_create([queueName cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_SERIAL);\n\n        dispatch_sync(_fileQueue, ^{\n            _fileManager = [NSFileManager new];\n            \n            [self makeDirectory];\n            [self listDirectory];\n            [self checkDiskStatus];\n        });\n    }\n    return self;\n}\n\n- (void)makeDirectory\n{\n    BOOL isFolderExist = [_fileManager fileExistsAtPath:_folderPath];\n    if (!isFolderExist) {\n        [_fileManager createDirectoryAtPath:_folderPath withIntermediateDirectories:YES attributes:nil error:nil];\n    }\n}\n\n- (void)listDirectory\n{\n    _creatingFiles = [[NSMutableDictionary alloc] init];\n\n    NSArray* filenames = [_fileManager contentsOfDirectoryAtPath:_folderPath error:nil];\n    _fileNames = [[NSMutableDictionary alloc] initWithCapacity:[filenames count]];\n    for (NSString* filename in filenames) {\n        [_fileNames setObject:@(1) forKey:filename];\n    }\n}\n\n// Execute in the _fileQueue\n- (void)checkDiskStatus\n{\n    NSDictionary* fileAttributes = [_fileManager attributesOfFileSystemForPath:@\"/\" error:nil];\n    unsigned long long freeSize = [[fileAttributes objectForKey:NSFileSystemFreeSize] unsignedLongLongValue];\n\n    // set disk is full when free size is less than 20Mb\n    _isDiskFull = freeSize < 1024 * 1024 * 20;\n}\n\n- (void)asyncCreateFileWithName:(NSString*)name completed:(void (^)(FlyImageDataFile* dataFile))completed\n{\n    NSParameterAssert(name);\n    NSParameterAssert(completed);\n\n    // already exist\n    NSString* filePath = [_folderPath stringByAppendingPathComponent:name];\n    if ([self isFileExistWithName:name]) {\n        FlyImageDataFile* file = [[FlyImageDataFile alloc] initWithPath:filePath];\n        completed(file);\n        return;\n    }\n\n    // can't add more\n    if (_isDiskFull) {\n        completed(nil);\n        return;\n    }\n\n    // save all the blocks into _creatingFiles, waiting for callback\n    @synchronized(_creatingFiles)\n    {\n        if ([_creatingFiles objectForKey:name] == nil) {\n            [_creatingFiles setObject:[NSMutableArray arrayWithObject:completed] forKey:name];\n        } else {\n            NSMutableArray* blocks = [_creatingFiles objectForKey:name];\n            [blocks addObject:completed];\n        }\n    }\n\n    dispatch_async(_fileQueue, ^{\n        \n        NSMutableDictionary *attributes = [NSMutableDictionary dictionary];\n        [attributes setValue:NSFileProtectionCompleteUnlessOpen forKeyPath:NSFileProtectionKey];\n        \n        BOOL success = [_fileManager createFileAtPath:filePath contents:nil attributes:attributes];\n        if ( !success ) {\n            FlyImageErrorLog(@\"can't create file at path %@\", filePath);\n            \n\t\t\t// check if the disk is full\n            [self checkDiskStatus];\n            \n            [self afterCreateFile:nil name:name];\n            return;\n        }\n        \n        // update index\n        @synchronized (_fileNames) {\n            [_fileNames setObject:@(1) forKey:name];\n        }\n        \n        FlyImageDataFile *file = [[FlyImageDataFile alloc] initWithPath:filePath];\n        [self afterCreateFile:file name:name];\n    });\n}\n\n- (void)afterCreateFile:(FlyImageDataFile*)file name:(NSString*)name\n{\n\n    NSArray* blocks = nil;\n    @synchronized(_creatingFiles)\n    {\n        blocks = [[_creatingFiles objectForKey:name] copy];\n        [_creatingFiles removeObjectForKey:name];\n    }\n\n    dispatch_main_sync_safe(^{\n        for (  void (^block)(FlyImageDataFile *dataFile) in blocks) {\n            block( file );\n        }\n    });\n}\n\n- (void)addExistFileName:(NSString*)name\n{\n    NSParameterAssert(name);\n\n    @synchronized(_fileNames)\n    {\n        [_fileNames setObject:@(1) forKey:name];\n    }\n}\n\n- (FlyImageDataFile*)createFileWithName:(NSString*)name\n{\n    NSParameterAssert(name);\n\n    // already exist\n    NSString* filePath = [_folderPath stringByAppendingPathComponent:name];\n    if ([self isFileExistWithName:name]) {\n        return [[FlyImageDataFile alloc] initWithPath:filePath];\n    }\n\n    // can't add more\n    if (_isDiskFull) {\n        return nil;\n    }\n\n    NSMutableDictionary* attributes = [NSMutableDictionary dictionary];\n    [attributes setValue:NSFileProtectionCompleteUnlessOpen forKeyPath:NSFileProtectionKey];\n\n    BOOL success = [_fileManager createFileAtPath:filePath contents:nil attributes:attributes];\n    if (!success) {\n        FlyImageErrorLog(@\"can't create file at path %@\", filePath);\n\n        // check if the disk is full\n        [self checkDiskStatus];\n\n        return nil;\n    }\n\n    // update index\n    @synchronized(_fileNames)\n    {\n        [_fileNames setObject:@(1) forKey:name];\n    }\n\n    return [[FlyImageDataFile alloc] initWithPath:filePath];\n}\n\n- (BOOL)isFileExistWithName:(NSString*)name\n{\n    NSParameterAssert(name);\n\n    return [_fileNames objectForKey:name] != nil;\n}\n\n- (FlyImageDataFile*)retrieveFileWithName:(NSString*)name\n{\n    NSParameterAssert(name);\n\n    if (![self isFileExistWithName:name]) {\n        return nil;\n    }\n\n    NSString* filePath = [_folderPath stringByAppendingPathComponent:name];\n    FlyImageDataFile* file = [[FlyImageDataFile alloc] initWithPath:filePath];\n\n    return file;\n}\n\n- (void)removeFileWithName:(NSString*)name\n{\n    NSParameterAssert(name);\n\n    if (![self isFileExistWithName:name]) {\n        return;\n    }\n\n    // remove from the indexes first\n    @synchronized(_fileNames)\n    {\n        [_fileNames removeObjectForKey:name];\n    }\n\n    // delete file\n    dispatch_async(_fileQueue, ^{\n        [_fileManager removeItemAtPath:[_folderPath stringByAppendingPathComponent:name] error:nil];\n        \n        [self checkDiskStatus];\n    });\n}\n\n- (void)purgeWithExceptions:(NSArray*)names\n                     toSize:(NSUInteger)toSize\n                  completed:(void (^)(NSUInteger fileCount, NSUInteger totalSize))completed\n{\n    dispatch_async(_fileQueue, ^{\n        \n        // from array to dictionary\n        NSMutableDictionary *exceptions = [[NSMutableDictionary alloc] initWithCapacity:[names count]];\n        for (NSString *name in names) {\n            [exceptions setObject:@(1) forKey:name];\n        }\n        \n        NSUInteger totalSize = (NSUInteger)[[_fileManager attributesOfItemAtPath:_folderPath error:nil] fileSize];\n        \n        NSURL *folderURL = [NSURL fileURLWithPath:_folderPath isDirectory:YES];\n        NSArray *resourceKeys = @[NSURLIsDirectoryKey, NSURLNameKey, NSURLTotalFileAllocatedSizeKey];\n        \n        // This enumerator prefetches useful properties for our cache files.\n        NSDirectoryEnumerator *enumerator = [_fileManager enumeratorAtURL:folderURL\n                                               includingPropertiesForKeys:resourceKeys\n                                                                  options:NSDirectoryEnumerationSkipsHiddenFiles\n                                                             errorHandler:NULL];\n        \n        // TODO SORT\n        NSMutableArray *urlsToDelete = [[NSMutableArray alloc] init];\n        NSMutableArray *namesToDelete = [[NSMutableArray alloc] init];\n        for (NSURL *fileURL in enumerator) {\n            NSNumber *isDirectory;\n            [fileURL getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:nil];\n            \n            if ([isDirectory boolValue]) {\n                continue;\n            }\n            \n            NSString *fileName;\n            [fileURL getResourceValue:&fileName forKey:NSURLNameKey error:nil];\n            \n            // dont remove file in exceptions\n            if ( [exceptions objectForKey:fileName] != nil ) {\n                continue;\n            }\n            \n            NSNumber *fileSize;\n            [fileURL getResourceValue:&fileSize forKey:NSURLTotalFileAllocatedSizeKey error:nil];\n            \n            // dont remove more files\n            totalSize -= [fileSize unsignedLongValue];\n            if ( totalSize <= toSize ) {\n                break;\n            }\n            \n            [urlsToDelete addObject:fileURL];\n            [namesToDelete addObject:fileName];\n        }\n        \n        // remove file and index\n        for (NSURL *fileURL in urlsToDelete) {\n            [_fileManager removeItemAtURL:fileURL error:nil];\n        }\n        @synchronized (_fileNames) {\n            for (NSString *fileName in namesToDelete) {\n                [_fileNames removeObjectForKey:fileName];\n            }\n        }\n        \n        [self checkDiskStatus];\n        \n        if ( completed != nil ) {\n            NSUInteger fileCount = [_fileNames count];\n            completed( fileCount, fileCount == 0 ? 0 : totalSize );\n        }\n    });\n}\n\n- (void)calculateSizeWithCompletionBlock:(void (^)(NSUInteger fileCount, NSUInteger totalSize))block\n{\n    NSParameterAssert(block);\n\n    dispatch_async(_fileQueue, ^{\n        // dont count self folder\n        NSUInteger fileCount = MAX(0, [[[_fileManager enumeratorAtPath:_folderPath] allObjects] count] - 1);\n        NSUInteger totalSize = (NSUInteger)[[_fileManager attributesOfItemAtPath:_folderPath error:nil] fileSize];\n        \n        dispatch_main_async_safe(^{\n            block( fileCount, fileCount == 0 ? 0 : totalSize );\n        });\n    });\n}\n\n- (void)freeDiskSpaceWithCompletionBlock:(void (^)(NSUInteger freeSize))block\n{\n    NSParameterAssert(block);\n\n    dispatch_async(_fileQueue, ^{\n        NSDictionary *fileAttributes = [_fileManager attributesOfFileSystemForPath:@\"/\" error:nil];\n        NSUInteger freeSize = (NSUInteger)[[fileAttributes objectForKey:NSFileSystemFreeSize] unsignedLongLongValue];\n        \n        dispatch_main_async_safe(^{\n            block( freeSize );\n        });\n    });\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageDecoder.h",
    "content": "//\n//  FlyImageDecoder.h\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"FlyImageUtils.h\"\n\n/**\n *  Decode image file.\n */\n@interface FlyImageDecoder : NSObject\n\n/**\n *  Convert memory buffer to icon.\n *\n *  @param bytes    memory file\n *  @param offset   offset position at the memory file\n *  @param length   size of memory buffer\n *  @param drawSize render size\n */\n- (UIImage*)iconImageWithBytes:(void*)bytes\n                        offset:(size_t)offset\n                        length:(size_t)length\n                      drawSize:(CGSize)drawSize;\n\n/**\n *  Decode a single image file.\n *\n *  @param file            FlyImageDataFile instance\n *  @param contentType     only support PNG/JPEG\n *  @param bytes           address of the memory\n *  @param length          file size\n *  @param drawSize        drawing size, not image  size\n *  @param contentsGravity contentsGravity of the image\n *  @param cornerRadius    cornerRadius of the image\n */\n- (UIImage*)imageWithFile:(void*)file\n              contentType:(ImageContentType)contentType\n                    bytes:(void*)bytes\n                   length:(size_t)length\n                 drawSize:(CGSize)drawSize\n          contentsGravity:(NSString* const)contentsGravity\n             cornerRadius:(CGFloat)cornerRadius;\n\n#ifdef FLYIMAGE_WEBP\n- (UIImage*)imageWithWebPData:(NSData*)imageData hasAlpha:(BOOL*)hasAlpha;\n#endif\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageDecoder.m",
    "content": "//\n//  FlyImageDecoder.m\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"FlyImageDecoder.h\"\n#ifdef FLYIMAGE_WEBP\n#import \"webp/decode.h\"\n#endif\n\nstatic void __ReleaseAsset(void* info, const void* data, size_t size)\n{\n    if (info != NULL) {\n        CFRelease(info); // will cause dealloc of FlyImageDataFile\n    }\n}\n\n#ifdef FLYIMAGE_WEBP\n// This gets called when the UIImage gets collected and frees the underlying image.\nstatic void free_image_data(void* info, const void* data, size_t size)\n{\n    if (info != NULL) {\n        WebPFreeDecBuffer(&(((WebPDecoderConfig*)info)->output));\n        free(info);\n    }\n\n    if (data != NULL) {\n        free((void*)data);\n    }\n}\n#endif\n\n@implementation FlyImageDecoder\n\n- (UIImage*)iconImageWithBytes:(void*)bytes\n                        offset:(size_t)offset\n                        length:(size_t)length\n                      drawSize:(CGSize)drawSize\n{\n\n    // Create CGImageRef whose backing store *is* the mapped image table entry. We avoid a memcpy this way.\n    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, bytes + offset, length, __ReleaseAsset);\n\n    CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;\n    NSInteger bitsPerComponent = 8;\n    NSInteger bitsPerPixel = 4 * 8;\n    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();\n\n    static NSInteger bytesPerPixel = 4;\n    static float kAlignment = 64;\n    CGFloat screenScale = [FlyImageUtils contentsScale];\n    size_t bytesPerRow = ceil((drawSize.width * screenScale * bytesPerPixel) / kAlignment) * kAlignment;\n\n    CGImageRef imageRef = CGImageCreate(drawSize.width * screenScale,\n                                        drawSize.height * screenScale,\n                                        bitsPerComponent,\n                                        bitsPerPixel,\n                                        bytesPerRow,\n                                        colorSpace,\n                                        bitmapInfo,\n                                        dataProvider,\n                                        NULL,\n                                        false,\n                                        kCGRenderingIntentDefault);\n\n    CGDataProviderRelease(dataProvider);\n    CGColorSpaceRelease(colorSpace);\n\n    if (imageRef == nil) {\n        return nil;\n    }\n\n    UIImage* image = [[UIImage alloc] initWithCGImage:imageRef\n                                                scale:screenScale\n                                          orientation:UIImageOrientationUp];\n    CGImageRelease(imageRef);\n\n    return image;\n}\n\n- (CGImageRef)imageRefWithFile:(void*)file\n                   contentType:(ImageContentType)contentType\n                         bytes:(void*)bytes\n                        length:(size_t)length\n{\n    if (contentType == ImageContentTypeUnknown || contentType == ImageContentTypeGif || contentType == ImageContentTypeTiff) {\n        return nil;\n    }\n\n    // Create CGImageRef whose backing store *is* the mapped image table entry. We avoid a memcpy this way.\n    CGDataProviderRef dataProvider = nil;\n    CGImageRef imageRef = nil;\n    if (contentType == ImageContentTypeJPEG) {\n        CFRetain(file);\n        dataProvider = CGDataProviderCreateWithData(file, bytes, length, __ReleaseAsset);\n        imageRef = CGImageCreateWithJPEGDataProvider(dataProvider, NULL, YES, kCGRenderingIntentDefault);\n\n    } else if (contentType == ImageContentTypePNG) {\n        CFRetain(file);\n        dataProvider = CGDataProviderCreateWithData(file, bytes, length, __ReleaseAsset);\n        imageRef = CGImageCreateWithPNGDataProvider(dataProvider, NULL, YES, kCGRenderingIntentDefault);\n\n    } else if (contentType == ImageContentTypeWebP) {\n#ifdef FLYIMAGE_WEBP\n        // `WebPGetInfo` weill return image width and height\n        int width = 0, height = 0;\n        if (!WebPGetInfo(bytes, length, &width, &height)) {\n            return nil;\n        }\n\n        WebPDecoderConfig* config = malloc(sizeof(WebPDecoderConfig));\n        if (!WebPInitDecoderConfig(config)) {\n            return nil;\n        }\n\n        config->options.no_fancy_upsampling = 1;\n        config->options.bypass_filtering = 1;\n        config->options.use_threads = 1;\n        config->output.colorspace = MODE_RGBA;\n\n        // Decode the WebP image data into a RGBA value array\n        VP8StatusCode decodeStatus = WebPDecode(bytes, length, config);\n        if (decodeStatus != VP8_STATUS_OK) {\n            return nil;\n        }\n\n        // Construct UIImage from the decoded RGBA value array\n        uint8_t* data = WebPDecodeRGBA(bytes, length, &width, &height);\n        dataProvider = CGDataProviderCreateWithData(config, data, config->options.scaled_width * config->options.scaled_height * 4, free_image_data);\n\n        CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();\n        CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast;\n        CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;\n\n        imageRef = CGImageCreate(width, height, 8, 32, 4 * width, colorSpaceRef, bitmapInfo, dataProvider, NULL, YES, renderingIntent);\n#endif\n    }\n\n    if (dataProvider != nil) {\n        CGDataProviderRelease(dataProvider);\n    }\n\n    return imageRef;\n}\n\n- (UIImage*)imageWithFile:(void*)file\n              contentType:(ImageContentType)contentType\n                    bytes:(void*)bytes\n                   length:(size_t)length\n                 drawSize:(CGSize)drawSize\n          contentsGravity:(NSString* const)contentsGravity\n             cornerRadius:(CGFloat)cornerRadius\n{\n\n    CGImageRef imageRef = [self imageRefWithFile:file contentType:contentType bytes:bytes length:length];\n    if (imageRef == nil) {\n        return nil;\n    }\n\n    CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));\n    CGFloat contentsScale = 1;\n    if (drawSize.width < imageSize.width && drawSize.height < imageSize.height) {\n        contentsScale = [FlyImageUtils contentsScale];\n    }\n    CGSize contextSize = CGSizeMake(drawSize.width * contentsScale, drawSize.height * contentsScale);\n\n    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();\n    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);\n\n    int infoMask = (bitmapInfo & kCGBitmapAlphaInfoMask);\n    BOOL anyNonAlpha = (infoMask == kCGImageAlphaNone || infoMask == kCGImageAlphaNoneSkipFirst || infoMask == kCGImageAlphaNoneSkipLast);\n\n    // CGBitmapContextCreate doesn't support kCGImageAlphaNone with RGB.\n    // https://developer.apple.com/library/mac/#qa/qa1037/_index.html\n    if (cornerRadius > 0) {\n        bitmapInfo &= kCGImageAlphaPremultipliedLast;\n    } else if (infoMask == kCGImageAlphaNone && CGColorSpaceGetNumberOfComponents(colorSpace) > 1) {\n        // Unset the old alpha info.\n        bitmapInfo &= ~kCGBitmapAlphaInfoMask;\n\n        // Set noneSkipFirst.\n        bitmapInfo |= kCGImageAlphaNoneSkipFirst;\n    }\n    // Some PNGs tell us they have alpha but only 3 components. Odd.\n    else if (!anyNonAlpha && CGColorSpaceGetNumberOfComponents(colorSpace) == 3) {\n        // Unset the old alpha info.\n        bitmapInfo &= ~kCGBitmapAlphaInfoMask;\n        bitmapInfo |= kCGImageAlphaPremultipliedFirst;\n    }\n\n    // It calculates the bytes-per-row based on the bitsPerComponent and width arguments.\n    static NSInteger bytesPerPixel = 4;\n    static float kAlignment = 64;\n    size_t bytesPerRow = ceil((contextSize.width * bytesPerPixel) / kAlignment) * kAlignment;\n\n    CGContextRef context = CGBitmapContextCreate(NULL, contextSize.width, contextSize.height, CGImageGetBitsPerComponent(imageRef), bytesPerRow, colorSpace, bitmapInfo);\n    CGColorSpaceRelease(colorSpace);\n\n    // If failed, return undecompressed image\n    if (!context) {\n        UIImage* image = [[UIImage alloc] initWithCGImage:imageRef\n                                                    scale:contentsScale\n                                              orientation:UIImageOrientationUp];\n        CGImageRelease(imageRef);\n        return image;\n    }\n\n    CGContextScaleCTM(context, contentsScale, contentsScale);\n    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);\n\n    CGRect contextBounds = CGRectMake(0, 0, drawSize.width, drawSize.height);\n\n    // Clip to a rounded rect\n    if (cornerRadius > 0) {\n        CGPathRef path = _FICDCreateRoundedRectPath(contextBounds, cornerRadius);\n        CGContextAddPath(context, path);\n        CFRelease(path);\n        CGContextEOClip(context);\n    }\n\n    CGContextDrawImage(context, _FlyImageCalcDrawBounds(imageSize,\n                                                        drawSize,\n                                                        contentsGravity),\n                       imageRef);\n\n    CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);\n    CGContextRelease(context);\n\n    UIImage* decompressedImage = [UIImage imageWithCGImage:decompressedImageRef\n                                                     scale:contentsScale\n                                               orientation:UIImageOrientationUp];\n\n    CGImageRelease(decompressedImageRef);\n    CGImageRelease(imageRef);\n\n    return decompressedImage;\n}\n\n#ifdef FLYIMAGE_WEBP\n- (UIImage*)imageWithWebPData:(NSData*)imageData hasAlpha:(BOOL*)hasAlpha\n{\n\n    // `WebPGetInfo` weill return image width and height\n    int width = 0, height = 0;\n    if (!WebPGetInfo(imageData.bytes, imageData.length, &width, &height)) {\n        return nil;\n    }\n\n    WebPDecoderConfig* config = malloc(sizeof(WebPDecoderConfig));\n    if (!WebPInitDecoderConfig(config)) {\n        return nil;\n    }\n\n    config->options.no_fancy_upsampling = 1;\n    config->options.bypass_filtering = 1;\n    config->options.use_threads = 1;\n    config->output.colorspace = MODE_RGBA;\n\n    // Decode the WebP image data into a RGBA value array\n    VP8StatusCode decodeStatus = WebPDecode(imageData.bytes, imageData.length, config);\n    if (decodeStatus != VP8_STATUS_OK) {\n        return nil;\n    }\n\n    // set alpha value\n    if (hasAlpha != nil) {\n        *hasAlpha = config->input.has_alpha;\n    }\n\n    // Construct UIImage from the decoded RGBA value array\n    uint8_t* data = WebPDecodeRGBA(imageData.bytes, imageData.length, &width, &height);\n    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(config, data, config->options.scaled_width * config->options.scaled_height * 4, free_image_data);\n\n    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();\n    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast;\n    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;\n\n    CGImageRef imageRef = CGImageCreate(width, height, 8, 32, 4 * width, colorSpaceRef, bitmapInfo, dataProvider, NULL, YES, renderingIntent);\n    UIImage* decodeImage = [UIImage imageWithCGImage:imageRef];\n\n    UIGraphicsBeginImageContextWithOptions(decodeImage.size, !config->input.has_alpha, 1);\n    [decodeImage drawInRect:CGRectMake(0, 0, decodeImage.size.width, decodeImage.size.height)];\n    UIImage* decompressedImage = UIGraphicsGetImageFromCurrentImageContext();\n    UIGraphicsEndImageContext();\n\n    return decompressedImage;\n}\n#endif\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageDownloader.h",
    "content": "//\n//  FlyImageDownloader.h\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\ntypedef void (^FlyImageDownloadProgressBlock)(float progress);\ntypedef void (^FlyImageDownloadSuccessBlock)(NSURLRequest* request, NSURL* filePath);\ntypedef void (^FlyImageDownloadFailedBlock)(NSURLRequest* request, NSError* error);\ntypedef NSUUID FlyImageDownloadHandlerId; // Unique ID of handler\n\n@class FlyImageDownloader;\n@protocol FlyImageDownloaderDelegate <NSObject>\n\n@optional\n/**\n *  Callback before sending request.\n */\n- (void)FlyImageDownloader:(FlyImageDownloader*)manager\n           willSendRequest:(NSURLRequest*)request;\n\n/**\n *  Callback after complete download.\n */\n- (void)FlyImageDownloader:(FlyImageDownloader*)manager\n        didReceiveResponse:(NSURLResponse*)response\n                  filePath:(NSURL*)filePath\n                     error:(NSError*)error\n                   request:(NSURLRequest*)request;\n\n/**\n *  Callback after cancel some request.\n */\n- (void)FlyImageDownloader:(FlyImageDownloader*)manager\n         willCancelRequest:(NSURLRequest*)request;\n\n@end\n\n@interface FlyImageDownloader : NSObject\n\n@property (nonatomic, weak) id<FlyImageDownloaderDelegate> delegate;\n@property (nonatomic, copy) NSString* destinationPath;\n@property (nonatomic, assign) NSInteger maxDownloadingCount; // Default is 5;\n\n/**\n *  Create a FlyImageDownloader with a default destination path.\n */\n+ (instancetype)sharedInstance;\n\n/**\n *  Create a FlyImageDownloader with a specific destination path.\n */\n- (instancetype)initWithDestinationPath:(NSString*)destinationPath;\n\n- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request;\n\n- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request\n                                                 success:(FlyImageDownloadSuccessBlock)success\n                                                  failed:(FlyImageDownloadFailedBlock)failed;\n\n/**\n *  Send a download request with callbacks\n */\n- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request\n                                                progress:(FlyImageDownloadProgressBlock)progress\n                                                 success:(FlyImageDownloadSuccessBlock)success\n                                                  failed:(FlyImageDownloadFailedBlock)failed;\n\n/**\n *  Cancel a downloading request.\n *\n *  @param handlerId can't be nil\n */\n- (void)cancelDownloadHandler:(FlyImageDownloadHandlerId*)handlerId;\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageDownloader.m",
    "content": "//\n//  FlyImageDownloader.m\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"FlyImageDownloader.h\"\n#import \"AFNetworking.h\"\n#import \"FlyImageUtils.h\"\n#import \"FlyImageDataFileManager.h\"\n#import \"FlyImageCache.h\"\n#import <objc/runtime.h>\n#import <CommonCrypto/CommonDigest.h>\n\n@interface FlyImageDownloaderResponseHandler : NSObject\n@property (nonatomic, strong) NSUUID* uuid;\n@property (nonatomic, strong) FlyImageDownloadProgressBlock processingBlock;\n@property (nonatomic, strong) FlyImageDownloadSuccessBlock successBlock;\n@property (nonatomic, strong) FlyImageDownloadFailedBlock failedBlock;\n@end\n\n@implementation FlyImageDownloaderResponseHandler\n\n- (instancetype)initWithUUID:(NSUUID*)uuid\n                    progress:(FlyImageDownloadProgressBlock)progress\n                     success:(FlyImageDownloadSuccessBlock)success\n                      failed:(FlyImageDownloadFailedBlock)failed\n{\n    if (self = [self init]) {\n        self.uuid = uuid;\n        self.processingBlock = progress;\n        self.successBlock = success;\n        self.failedBlock = failed;\n    }\n    return self;\n}\n\n@end\n\n@interface FlyImageDownloaderMergedTask : NSObject\n@property (nonatomic, strong) NSString* identifier;\n@property (nonatomic, strong) NSMutableArray* handlers;\n@property (nonatomic, strong) NSURLSessionDownloadTask* task;\n@end\n\n@implementation FlyImageDownloaderMergedTask\n\n- (instancetype)initWithIdentifier:(NSString*)identifier task:(NSURLSessionDownloadTask*)task\n{\n    if (self = [self init]) {\n        self.identifier = identifier;\n        self.task = task;\n        self.handlers = [[NSMutableArray alloc] init];\n    }\n    return self;\n}\n\n- (void)addResponseHandler:(FlyImageDownloaderResponseHandler*)handler\n{\n    [self.handlers addObject:handler];\n}\n\n- (void)removeResponseHandler:(FlyImageDownloaderResponseHandler*)handler\n{\n    [self.handlers removeObject:handler];\n}\n\n- (void)clearHandlers\n{\n    [self.handlers removeAllObjects];\n}\n\n@end\n\n@interface NSString (Extension)\n- (NSString*)md5;\n@end\n\n@implementation NSString (Extension)\n- (NSString*)md5\n{\n    const char* cStr = [self UTF8String];\n    unsigned char result[CC_MD5_DIGEST_LENGTH];\n    CC_MD5(cStr, (CC_LONG)strlen(cStr), result); // This is the md5 call\n    return [NSString stringWithFormat:@\"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\",\n                                      result[0],\n                                      result[1],\n                                      result[2],\n                                      result[3],\n                                      result[4],\n                                      result[5],\n                                      result[6],\n                                      result[7],\n                                      result[8],\n                                      result[9],\n                                      result[10],\n                                      result[11],\n                                      result[12],\n                                      result[13],\n                                      result[14],\n                                      result[15]];\n}\n@end\n\n@interface FlyImageDownloader ()\n@property (nonatomic, strong) NSMutableDictionary* downloadFile;\n@property (nonatomic, strong) NSMutableDictionary* mergedTasks;\n@property (nonatomic, strong) NSMutableArray* queuedMergedTasks;\n@property (nonatomic, assign) NSInteger activeRequestCount;\n@property (nonatomic, strong) dispatch_queue_t synchronizationQueue;\n@property (nonatomic, strong) dispatch_queue_t responseQueue;\n@end\n\n@implementation FlyImageDownloader {\n    AFURLSessionManager* _sessionManager;\n}\n\n+ (instancetype)sharedInstance\n{\n    static dispatch_once_t onceToken;\n    static FlyImageDownloader* __instance = nil;\n    dispatch_once(&onceToken, ^{\n\t\tNSString *folderPath = [FlyImageCache sharedInstance].dataFileManager.folderPath;\n\t\t__instance = [[[self class] alloc] initWithDestinationPath:folderPath];\n    });\n\n    return __instance;\n}\n\n- (instancetype)initWithDestinationPath:(NSString*)destinationPath\n{\n    if (self = [self init]) {\n\n        _maxDownloadingCount = 5;\n        _mergedTasks = [[NSMutableDictionary alloc] initWithCapacity:_maxDownloadingCount];\n        _queuedMergedTasks = [[NSMutableArray alloc] initWithCapacity:_maxDownloadingCount];\n\n        _destinationPath = [destinationPath copy];\n\n        NSString* name = [NSString stringWithFormat:@\"com.flyimage.imagedownloader.synchronizationqueue-%@\", [[NSUUID UUID] UUIDString]];\n        self.synchronizationQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_SERIAL);\n\n        name = [NSString stringWithFormat:@\"com.flyimage.imagedownloader.responsequeue-%@\", [[NSUUID UUID] UUIDString]];\n        self.responseQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_CONCURRENT);\n\n        NSString* configurationIdentifier = [NSString stringWithFormat:@\"com.flyimage.downloadsession.%@\", [[NSUUID UUID] UUIDString]];\n        NSURLSessionConfiguration* configuration = [FlyImageDownloader configurationWithIdentifier:configurationIdentifier];\n        _sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];\n    }\n    return self;\n}\n\n+ (NSURLSessionConfiguration*)configurationWithIdentifier:(NSString*)identifier\n{\n    NSURLSessionConfiguration* configuration;\n#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1100)\n    configuration = [NSURLSessionConfiguration defaultSessionConfiguration];\n#else\n    configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier];\n#endif\n\n    configuration.HTTPShouldSetCookies = YES;\n    configuration.HTTPShouldUsePipelining = NO;\n\n    configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;\n    configuration.allowsCellularAccess = YES;\n\n    return configuration;\n}\n\n- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request\n{\n    return [self downloadImageForURLRequest:request\n                                   progress:nil\n                                    success:nil\n                                     failed:nil];\n}\n\n- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request\n                                                 success:(FlyImageDownloadSuccessBlock)success\n                                                  failed:(FlyImageDownloadFailedBlock)failed\n{\n    return [self downloadImageForURLRequest:request\n                                   progress:nil\n                                    success:success\n                                     failed:failed];\n}\n\n- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request\n                                                progress:(FlyImageDownloadProgressBlock)progress\n                                                 success:(FlyImageDownloadSuccessBlock)success\n                                                  failed:(FlyImageDownloadFailedBlock)failed\n{\n    NSParameterAssert(request != nil);\n\n    __block FlyImageDownloadHandlerId* handlerId = nil;\n    dispatch_sync(_synchronizationQueue, ^{\n        if (request.URL.absoluteString == nil) {\n            if (failed) {\n                NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorBadURL userInfo:nil];\n                dispatch_main_sync_safe(^{\n                    failed(request, error);\n                });\n            }\n            return;\n        }\n\n        NSString *identifier = [request.URL.absoluteString md5];\n        handlerId = [NSUUID UUID];\n        \n        // 1) Append the success and failure blocks to a pre-existing request if it already exists\n        FlyImageDownloaderMergedTask *existingMergedTask = self.mergedTasks[identifier];\n        if (existingMergedTask != nil) {\n            FlyImageDownloaderResponseHandler *handler = [[FlyImageDownloaderResponseHandler alloc]\n                                                          initWithUUID:handlerId\n                                                          progress:progress\n                                                          success:success\n                                                          failed:failed];\n            [existingMergedTask addResponseHandler:handler];\n            return;\n        }\n        \n        __weak __typeof__(self) weakSelf = self;\n        NSURLSessionDownloadTask *task =\n        [_sessionManager downloadTaskWithRequest:request\n                                        progress:^(NSProgress * _Nonnull downloadProgress) {\n\t\t\t\t\t\t\t\t\t\t\tdispatch_async(weakSelf.responseQueue, ^{\n\t\t\t\t\t\t\t\t\t\t\t\tFlyImageDownloaderMergedTask *existingMergedTask = weakSelf.mergedTasks[identifier];\n\t\t\t\t\t\t\t\t\t\t\t\tfor (FlyImageDownloaderResponseHandler *hanlder in existingMergedTask.handlers) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( hanlder.processingBlock != nil ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdispatch_main_async_safe(^{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thanlder.processingBlock( downloadProgress.fractionCompleted );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n                                     destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {\n                                         return [NSURL fileURLWithPath:[_destinationPath stringByAppendingPathComponent:identifier]];\n                                     }\n                               completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {\n\t\t\t\t\t\t\t\t   dispatch_async(weakSelf.responseQueue, ^{\n\t\t\t\t\t\t\t\t\t   __strong __typeof__(weakSelf) strongSelf = weakSelf;\n\t\t\t\t\t\t\t\t\t   if ( [_delegate respondsToSelector:@selector(FlyImageDownloader:didReceiveResponse:filePath:error:request:)] ) {\n\t\t\t\t\t\t\t\t\t\t   dispatch_main_sync_safe(^{\n\t\t\t\t\t\t\t\t\t\t\t   [_delegate FlyImageDownloader:strongSelf\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   didReceiveResponse:response\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t filePath:filePath\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\terror:error\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  request:request];\n\t\t\t\t\t\t\t\t\t\t   });\n\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t   \n\t\t\t\t\t\t\t\t\t   FlyImageDownloaderMergedTask *mergedTask = strongSelf.mergedTasks[identifier];\n\t\t\t\t\t\t\t\t\t   if (error != nil) {\n\t\t\t\t\t\t\t\t\t\t   for (FlyImageDownloaderResponseHandler *handler in mergedTask.handlers) {\n\t\t\t\t\t\t\t\t\t\t\t   if (handler.failedBlock) {\n\t\t\t\t\t\t\t\t\t\t\t\t   handler.failedBlock(request, error);\n\t\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t   \n\t\t\t\t\t\t\t\t\t\t   // remove error file\n\t\t\t\t\t\t\t\t\t\t   [[NSFileManager defaultManager] removeItemAtURL:filePath error:nil];\n\t\t\t\t\t\t\t\t\t   }else{\n\t\t\t\t\t\t\t\t\t\t   for (FlyImageDownloaderResponseHandler *handler in mergedTask.handlers) {\n\t\t\t\t\t\t\t\t\t\t\t   if (handler.successBlock) {\n\t\t\t\t\t\t\t\t\t\t\t\t   handler.successBlock(request, filePath);\n\t\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t   \n\t\t\t\t\t\t\t\t\t   // remove exist task\n\t\t\t\t\t\t\t\t\t   [strongSelf.mergedTasks removeObjectForKey:identifier];\n\t\t\t\t\t\t\t\t\t   \n\t\t\t\t\t\t\t\t\t   [strongSelf safelyDecrementActiveTaskCount];\n\t\t\t\t\t\t\t\t\t   [strongSelf safelyStartNextTaskIfNecessary];\n\t\t\t\t\t\t\t\t   });\n                               }];\n        \n        // 4) Store the response handler for use when the request completes\n\t\texistingMergedTask = [[FlyImageDownloaderMergedTask alloc] initWithIdentifier:identifier task:task];\n        self.mergedTasks[ identifier ] = existingMergedTask;\n        \n        FlyImageDownloaderResponseHandler *handler = [[FlyImageDownloaderResponseHandler alloc]\n                                                      initWithUUID:handlerId\n                                                      progress:progress\n                                                      success:success\n                                                      failed:failed];\n        [existingMergedTask addResponseHandler:handler];\n        \n        // 5) Either start the request or enqueue it depending on the current active request count\n        if ([self isActiveRequestCountBelowMaximumLimit]) {\n            [self startMergedTask:existingMergedTask];\n        } else {\n            [self enqueueMergedTask:existingMergedTask];\n        }\n    });\n\n    return handlerId;\n}\n\n- (void)cancelDownloadHandler:(FlyImageDownloadHandlerId*)handlerId\n{\n    NSParameterAssert(handlerId != nil);\n\n    dispatch_sync(_synchronizationQueue, ^{\n        \n        FlyImageDownloaderMergedTask *matchedTask = nil;\n        FlyImageDownloaderResponseHandler *matchedHandler = nil;\n        \n        for (NSString *URLIdentifier in self.mergedTasks) {\n            FlyImageDownloaderMergedTask *mergedTask = self.mergedTasks[ URLIdentifier ];\n            for (FlyImageDownloaderResponseHandler *handler in mergedTask.handlers) {\n                if ( [handler.uuid isEqual:handlerId] ) {\n                    matchedHandler = handler;\n                    matchedTask = mergedTask;\n                    break;\n                }\n            }\n        }\n        \n        if ( matchedTask == nil ) {\n            for (FlyImageDownloaderMergedTask *mergedTask in _queuedMergedTasks) {\n                for (FlyImageDownloaderResponseHandler *handler in mergedTask.handlers) {\n                    if ( [handler.uuid isEqual:handlerId] ) {\n                        matchedHandler = handler;\n                        matchedTask = mergedTask;\n                        break;\n                    }\n                }\n            }\n        }\n        \n        if ( matchedTask == nil || matchedHandler == nil ) {\n            return;\n        }\n        [matchedTask removeResponseHandler:matchedHandler];\n        \n        NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:nil];\n        dispatch_main_sync_safe(^{\n            if ( matchedHandler.failedBlock != nil ){\n                matchedHandler.failedBlock(nil, error);\n            }\n        });\n\t\t\n        // remove this task from both merged and queued tasks\n        if (matchedTask.handlers.count == 0) {\n\t\t\t\n\t\t\tif ( [_delegate respondsToSelector:@selector(FlyImageDownloader:willCancelRequest:)] ) {\n\t\t\t\tdispatch_main_sync_safe(^{\n\t\t\t\t\t[_delegate FlyImageDownloader:self willCancelRequest:matchedTask.task.originalRequest];\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n            [matchedTask.task cancel];\n            \n            [self.mergedTasks removeObjectForKey:matchedTask.identifier];\n            [_queuedMergedTasks removeObject:matchedTask];\n        }\n    });\n}\n\n- (BOOL)isActiveRequestCountBelowMaximumLimit\n{\n    return self.activeRequestCount < self.maxDownloadingCount;\n}\n\n- (void)startMergedTask:(FlyImageDownloaderMergedTask*)mergedTask\n{\n    if ([_delegate respondsToSelector:@selector(FlyImageDownloader:willSendRequest:)]) {\n        dispatch_main_sync_safe(^{\n\t\t\t[_delegate FlyImageDownloader:self willSendRequest:mergedTask.task.originalRequest];\n        });\n    }\n\n    [mergedTask.task resume];\n    ++self.activeRequestCount;\n}\n\n- (void)enqueueMergedTask:(FlyImageDownloaderMergedTask*)mergedTask\n{\n    // default is AFImageDownloadPrioritizationLIFO\n    [_queuedMergedTasks insertObject:mergedTask atIndex:0];\n}\n\n- (FlyImageDownloaderMergedTask*)dequeueMergedTask\n{\n    FlyImageDownloaderMergedTask* mergedTask = nil;\n    mergedTask = [_queuedMergedTasks lastObject];\n    [self.queuedMergedTasks removeObject:mergedTask];\n    return mergedTask;\n}\n\n- (void)safelyDecrementActiveTaskCount\n{\n    dispatch_sync(_synchronizationQueue, ^{\n        if (self.activeRequestCount > 0) {\n            self.activeRequestCount -= 1;\n        }\n    });\n}\n\n- (void)safelyStartNextTaskIfNecessary\n{\n    dispatch_sync(_synchronizationQueue, ^{\n        while ([self isActiveRequestCountBelowMaximumLimit] && [_queuedMergedTasks count] > 0 ) {\n            FlyImageDownloaderMergedTask *mergedTask = [self dequeueMergedTask];\n            [self startMergedTask:mergedTask];\n        }\n    });\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageEncoder.h",
    "content": "//\n//  FlyImageEncoder.h\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\ntypedef void (^FFlyImageEncoderDrawingBlock)(CGContextRef context, CGRect contextBounds);\n\n/**\n *  Convert an image to bitmap format.\n */\n@interface FlyImageEncoder : NSObject\n\n/**\n *  Draw an image, and save the bitmap data into memory buffer.\n *\n *  @param size         image size\n *  @param bytes        memory buffer\n *  @param drawingBlock drawing function\n */\n- (void)encodeWithImageSize:(CGSize)size\n                      bytes:(void*)bytes\n               drawingBlock:(FFlyImageEncoderDrawingBlock)drawingBlock;\n\n/**\n *  Calculate buffer size with image size.\n *\n *  @param size image size\n */\n+ (size_t)dataLengthWithImageSize:(CGSize)size;\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageEncoder.m",
    "content": "//\n//  FlyImageEncoder.m\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"FlyImageEncoder.h\"\n#import \"FlyImageUtils.h\"\n\n@implementation FlyImageEncoder\n\nstatic NSInteger __bytesPerPixel = 4;\nstatic NSInteger __bitsPerComponent = 8;\nstatic float __alignmentSize = 64;\n\n- (void)encodeWithImageSize:(CGSize)size\n                      bytes:(void*)bytes\n               drawingBlock:(FFlyImageEncoderDrawingBlock)drawingBlock\n{\n\n    CGFloat screenScale = [FlyImageUtils contentsScale];\n    CGSize pixelSize = CGSizeMake(size.width * screenScale, size.height * screenScale);\n\n    // It calculates the bytes-per-row based on the __bitsPerComponent and width arguments.\n    size_t bytesPerRow = ceil((pixelSize.width * __bytesPerPixel) / __alignmentSize) * __alignmentSize;\n\n    CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;\n    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();\n\n    CGContextRef context = CGBitmapContextCreate(bytes,\n                                                 pixelSize.width,\n                                                 pixelSize.height,\n                                                 __bitsPerComponent,\n                                                 bytesPerRow,\n                                                 colorSpace,\n                                                 bitmapInfo);\n    CGColorSpaceRelease(colorSpace);\n\n    CGContextTranslateCTM(context, 0, pixelSize.height);\n    CGContextScaleCTM(context, 1, -1);\n\n    // Call drawing block to allow client to draw into the context\n    CGRect contextBounds = CGRectZero;\n    contextBounds.size = pixelSize;\n    CGContextClearRect(context, contextBounds);\n\n    drawingBlock(context, contextBounds);\n    CGContextRelease(context);\n}\n\n+ (size_t)dataLengthWithImageSize:(CGSize)size\n{\n\n    CGFloat screenScale = [FlyImageUtils contentsScale];\n    CGSize pixelSize = CGSizeMake(size.width * screenScale, size.height * screenScale);\n\n    size_t bytesPerRow = ceil((pixelSize.width * __bytesPerPixel) / __alignmentSize) * __alignmentSize;\n    CGFloat imageLength = bytesPerRow * (NSInteger)pixelSize.height;\n\n    int pageSize = [FlyImageUtils pageSize];\n    size_t bytesToAppend = ceil(imageLength / pageSize) * pageSize;\n\n    return bytesToAppend;\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageIconCache.h",
    "content": "//\n//  FlyImageIconCache.h\n//  Demo\n//\n//  Created by Norris Tong on 4/2/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"FlyImageCacheProtocol.h\"\n\n/**\n *\tDraw the icon in a background thread.\n *\n *  @param context\tdrawing context\n *  @param contextBounds  image size\n */\ntypedef void (^FlyImageCacheDrawingBlock)(CGContextRef context, CGRect contextBounds);\n\n/**\n *\tFlyImageIconCache will draw icons into one big file, \n *  and will get great performace when try to render multiple icons in one screen.\n */\n@interface FlyImageIconCache : NSObject <FlyImageCacheProtocol>\n\n/**\n *  Add an icon into the FlyImageIconCache.\n *\n *  @param key          unique key\n *  @param size         image size\n *  @param drawingBlock\n *  @param completed    callback after add, can be nil\n */\n- (void)addImageWithKey:(NSString*)key\n                   size:(CGSize)size\n           drawingBlock:(FlyImageCacheDrawingBlock)drawingBlock\n              completed:(FlyImageCacheRetrieveBlock)completed;\n\n/**\n *  FlyImageIconCache not support remove an icon from the cache, but you can replace an icon with the same key.\n *  But the new image must has the same size with the previous one.\n *\n *  @param key          unique key\n *  @param drawingBlock\n *  @param completed    callback after replace, can be nil\n */\n- (void)replaceImageWithKey:(NSString*)key\n               drawingBlock:(FlyImageCacheDrawingBlock)drawingBlock\n                  completed:(FlyImageCacheRetrieveBlock)completed;\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageIconCache.m",
    "content": "//\n//  FlyImageIconCache.m\n//  Demo\n//\n//  Created by Norris Tong on 4/2/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"FlyImageIconCache.h\"\n#import \"FlyImageDataFileManager.h\"\n#import \"FlyImageUtils.h\"\n#import \"FlyImageEncoder.h\"\n#import \"FlyImageDecoder.h\"\n#import \"FlyImageRetrieveOperation.h\"\n\nstatic NSString* kFlyImageKeyVersion = @\"v\";\nstatic NSString* kFlyImageKeyFile = @\"f\";\nstatic NSString* kFlyImageKeyImages = @\"i\";\nstatic NSString* kFlyImageKeyFilePointer = @\"p\";\n\n#define kImageInfoIndexWidth 0\n#define kImageInfoIndexHeight 1\n#define kImageInfoIndexOffset 2\n#define kImageInfoIndexLength 3\n#define kImageInfoCount 4\n\n@interface FlyImageIconCache ()\n@property (nonatomic, strong) FlyImageEncoder* encoder;\n@property (nonatomic, strong) FlyImageDecoder* decoder;\n@property (nonatomic, strong) FlyImageDataFile* dataFile;\n@property (nonatomic, strong) FlyImageDataFileManager* dataFileManager;\n@end\n\n@implementation FlyImageIconCache {\n    NSRecursiveLock* _lock;\n    NSString* _metaPath;\n\n    NSMutableDictionary* _metas;\n    NSMutableDictionary* _images;\n    NSMutableDictionary* _addingImages;\n    NSOperationQueue* _retrievingQueue;\n}\n\n+ (instancetype)sharedInstance\n{\n    static dispatch_once_t onceToken;\n    static FlyImageIconCache* __instance = nil;\n    dispatch_once(&onceToken, ^{\n\t\tNSString *metaPath = [[FlyImageUtils directoryPath] stringByAppendingPathComponent:@\"/__icons\"];\n        __instance = [[[self class] alloc] initWithMetaPath:metaPath];\n    });\n\n    return __instance;\n}\n\n- (instancetype)initWithMetaPath:(NSString*)metaPath\n{\n    if (self = [self init]) {\n\n        _lock = [[NSRecursiveLock alloc] init];\n        _addingImages = [[NSMutableDictionary alloc] init];\n        _retrievingQueue = [NSOperationQueue new];\n        _retrievingQueue.qualityOfService = NSQualityOfServiceUserInteractive;\n        _retrievingQueue.maxConcurrentOperationCount = 6;\n\n        _metaPath = [metaPath copy];\n        NSString* folderPath = [[_metaPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@\"/files\"];\n        self.dataFileManager = [[FlyImageDataFileManager alloc] initWithFolderPath:folderPath];\n        [self loadMetadata];\n\n        _decoder = [[FlyImageDecoder alloc] init];\n        _encoder = [[FlyImageEncoder alloc] init];\n\n        [[NSNotificationCenter defaultCenter] addObserver:self\n                                                 selector:@selector(onWillTerminate)\n                                                     name:UIApplicationWillTerminateNotification\n                                                   object:nil];\n    }\n    return self;\n}\n\n#pragma mark - LifeCircle\n- (void)onWillTerminate\n{\n    // 取消内存映射\n    _dataFile = nil;\n    [_retrievingQueue cancelAllOperations];\n}\n\n- (void)dealloc\n{\n    _dataFile = nil;\n    [_retrievingQueue cancelAllOperations];\n}\n\n#pragma mark - APIs\n- (void)addImageWithKey:(NSString*)key\n                   size:(CGSize)size\n           drawingBlock:(FlyImageCacheDrawingBlock)drawingBlock\n              completed:(FlyImageCacheRetrieveBlock)completed\n{\n\n    NSParameterAssert(key != nil);\n    NSParameterAssert(drawingBlock != nil);\n\n    if ([self isImageExistWithKey:key]) {\n        [self asyncGetImageWithKey:key completed:completed];\n        return;\n    }\n\n    size_t bytesToAppend = [FlyImageEncoder dataLengthWithImageSize:size];\n    [self doAddImageWithKey:key\n                       size:size\n                     offset:-1\n                     length:bytesToAppend\n               drawingBlock:drawingBlock\n                  completed:completed];\n}\n\n- (void)doAddImageWithKey:(NSString*)key\n                     size:(CGSize)size\n                   offset:(size_t)offset\n                   length:(size_t)length\n             drawingBlock:(FlyImageCacheDrawingBlock)drawingBlock\n                completed:(FlyImageCacheRetrieveBlock)completed\n{\n\n    NSParameterAssert(completed != nil);\n\n    if (_dataFile == nil) {\n        if (completed != nil) {\n            completed(key, nil);\n        }\n        return;\n    }\n\n    if (completed != nil) {\n        @synchronized(_addingImages)\n        {\n            if ([_addingImages objectForKey:key] == nil) {\n                [_addingImages setObject:[NSMutableArray arrayWithObject:completed] forKey:key];\n            } else {\n                NSMutableArray* blocks = [_addingImages objectForKey:key];\n                [blocks addObject:completed];\n                return;\n            }\n        }\n    }\n\n    static dispatch_queue_t __drawingQueue = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n\t\tNSString *name = [NSString stringWithFormat:@\"com.flyimage.drawicon.%@\", [[NSUUID UUID] UUIDString]];\n        __drawingQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], NULL);\n    });\n\n    // 使用dispatch_sync 代替 dispatch_async，防止大规模写入时出现异常\n    dispatch_async(__drawingQueue, ^{\n\t\t\n\t\tsize_t newOffset = offset == -1 ? (size_t)_dataFile.pointer : offset;\n        if ( ![_dataFile prepareAppendDataWithOffset:newOffset length:length] ) {\n            [self afterAddImage:nil key:key];\n            return;\n        }\n        \n        [_encoder encodeWithImageSize:size bytes:_dataFile.address + newOffset drawingBlock:drawingBlock];\n        \n        BOOL success = [_dataFile appendDataWithOffset:newOffset length:length];\n        if ( !success ) {\n            // TODO: consider rollback\n            [self afterAddImage:nil key:key];\n            return;\n        }\n        \n        // number of dataFile, width of image, height of image, offset, length\n        @synchronized (_images) {\n            NSArray *imageInfo = @[ @(size.width),\n                                    @(size.height),\n                                    @(newOffset),\n                                    @(length) ];\n            \n            [_images setObject:imageInfo forKey:key];\n        }\n        \n        // callback with image\n        UIImage *image = [_decoder iconImageWithBytes:_dataFile.address\n                                                 offset:newOffset\n                                                 length:length\n\t\t\t\t\t\t\t\t\t\t\t   drawSize:size];\n        [self afterAddImage:image key:key];\n        \n        // save meta\n        [self saveMetadata];\n    });\n}\n\n- (void)afterAddImage:(UIImage*)image key:(NSString*)key\n{\n    NSArray* blocks = nil;\n    @synchronized(_addingImages)\n    {\n        blocks = [[_addingImages objectForKey:key] copy];\n        [_addingImages removeObjectForKey:key];\n    }\n\n    dispatch_main_sync_safe(^{\n        for ( FlyImageCacheRetrieveBlock block in blocks) {\n            block( key, image );\n        }\n    });\n}\n\n- (void)replaceImageWithKey:(NSString*)key\n               drawingBlock:(FlyImageCacheDrawingBlock)drawingBlock\n                  completed:(FlyImageCacheRetrieveBlock)completed\n{\n\n    NSParameterAssert(key != nil);\n    NSParameterAssert(drawingBlock != nil);\n\n    id imageInfo = nil;\n    @synchronized(_images)\n    {\n        imageInfo = _images[key];\n    }\n    if (imageInfo == nil) {\n        if (completed != nil) {\n            completed(key, nil);\n        }\n        return;\n    }\n\n    // width of image, height of image, offset, length\n    CGFloat imageWidth = [[imageInfo objectAtIndex:kImageInfoIndexWidth] floatValue];\n    CGFloat imageHeight = [[imageInfo objectAtIndex:kImageInfoIndexHeight] floatValue];\n    size_t imageOffset = [[imageInfo objectAtIndex:kImageInfoIndexOffset] unsignedLongValue];\n    size_t imageLength = [[imageInfo objectAtIndex:kImageInfoIndexLength] unsignedLongValue];\n\n    CGSize size = CGSizeMake(imageWidth, imageHeight);\n    [self doAddImageWithKey:key\n                       size:size\n                     offset:imageOffset\n                     length:imageLength\n               drawingBlock:drawingBlock\n                  completed:completed];\n}\n\n- (void)removeImageWithKey:(NSString*)key\n{\n    @synchronized(_images)\n    {\n        [_images removeObjectForKey:key];\n    }\n}\n\n- (void)changeImageKey:(NSString*)oldKey newKey:(NSString*)newKey\n{\n    @synchronized(_images)\n    {\n\n        id imageInfo = [_images objectForKey:oldKey];\n        if (imageInfo == nil) {\n            return;\n        }\n\n        [_images setObject:imageInfo forKey:newKey];\n        [_images removeObjectForKey:oldKey];\n    }\n}\n\n- (BOOL)isImageExistWithKey:(NSString*)key\n{\n    @synchronized(_images)\n    {\n        return [_images objectForKey:key] != nil;\n    }\n}\n\n- (void)asyncGetImageWithKey:(NSString*)key completed:(FlyImageCacheRetrieveBlock)completed\n{\n    NSParameterAssert(key != nil);\n    NSParameterAssert(completed != nil);\n\n    if (_dataFile == nil) {\n        completed(key, nil);\n        return;\n    }\n\n    NSArray* imageInfo;\n    @synchronized(_images)\n    {\n        imageInfo = _images[key];\n    }\n\n    if (imageInfo == nil || [imageInfo count] < kImageInfoCount) {\n        completed(key, nil);\n        return;\n    }\n\n    // width of image, height of image, offset, length\n    CGFloat imageWidth = [[imageInfo objectAtIndex:kImageInfoIndexWidth] floatValue];\n    CGFloat imageHeight = [[imageInfo objectAtIndex:kImageInfoIndexHeight] floatValue];\n    size_t imageOffset = [[imageInfo objectAtIndex:kImageInfoIndexOffset] unsignedLongValue];\n    size_t imageLength = [[imageInfo objectAtIndex:kImageInfoIndexLength] unsignedLongValue];\n\n    __weak __typeof__(self) weakSelf = self;\n    FlyImageRetrieveOperation* operation = [[FlyImageRetrieveOperation alloc] initWithRetrieveBlock:^UIImage * {\n\t\treturn [weakSelf.decoder iconImageWithBytes:weakSelf.dataFile.address\n\t\t\t\t\t\t\t\t\t offset:imageOffset\n\t\t\t\t\t\t\t\t\t length:imageLength\n\t\t\t\t\t\t\t\t   drawSize:CGSizeMake(imageWidth, imageHeight)];\n\n    }];\n    operation.name = key;\n    [operation addBlock:completed];\n    [_retrievingQueue addOperation:operation];\n}\n\n- (void)cancelGetImageWithKey:(NSString*)key\n{\n    NSParameterAssert(key != nil);\n\n    for (FlyImageRetrieveOperation* operation in _retrievingQueue.operations) {\n        if (!operation.cancelled && !operation.finished && [operation.name isEqualToString:key]) {\n            [operation cancel];\n            return;\n        }\n    }\n}\n\n- (void)purge\n{\n    [self removeImages];\n\n    _dataFile = nil;\n    NSString* fileName = [_metas objectForKey:kFlyImageKeyFile];\n    if (fileName != nil) {\n        [self.dataFileManager removeFileWithName:fileName];\n        [self createDataFile:fileName];\n    }\n\n    [self saveMetadata];\n}\n\n- (void)removeImages\n{\n    @synchronized(_images)\n    {\n        [_images removeAllObjects];\n    }\n\n    [_retrievingQueue cancelAllOperations];\n\n    @synchronized(_addingImages)\n    {\n        for (NSString* key in _addingImages) {\n            NSArray* blocks = [_addingImages objectForKey:key];\n            dispatch_main_sync_safe(^{\n                for ( FlyImageCacheRetrieveBlock block in blocks) {\n                    block( key, nil );\n                }\n            });\n        }\n\n        [_addingImages removeAllObjects];\n    }\n}\n\n#pragma mark - Working with Metadata\n- (void)saveMetadata\n{\n    static dispatch_queue_t __metadataQueue = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n\t\tNSString *name = [NSString stringWithFormat:@\"com.flyimage.iconmeta.%@\", [[NSUUID UUID] UUIDString]];\n        __metadataQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], NULL);\n    });\n\n    dispatch_async(__metadataQueue, ^{\n        [_lock lock];\n        \n        NSData *data = [NSJSONSerialization dataWithJSONObject:[_metas copy] options:kNilOptions error:NULL];\n        BOOL fileWriteResult = [data writeToFile:_metaPath atomically:NO];\n        if (fileWriteResult == NO) {\n            FlyImageErrorLog(@\"couldn't save metadata\");\n        }\n        \n        [_lock unlock];\n    });\n}\n\n- (void)loadMetadata\n{\n    // load content from index file\n    NSError* error;\n    NSData* metadataData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:_metaPath] options:NSDataReadingMappedAlways error:&error];\n    if (error != nil || metadataData == nil) {\n        [self createMetadata];\n        return;\n    }\n\n    NSDictionary* parsedObject = (NSDictionary*)[NSJSONSerialization JSONObjectWithData:metadataData options:kNilOptions error:&error];\n    if (error != nil || parsedObject == nil) {\n        [self createMetadata];\n        return;\n    }\n\n    // 客户端升级后，图标极有可能发生变化，为了适应这种变化，自动清理本地缓存，所有图标都重新生成\n    NSString* lastVersion = [parsedObject objectForKey:kFlyImageKeyVersion];\n    NSString* currentVersion = [FlyImageUtils clientVersion];\n    if (lastVersion != nil && ![lastVersion isEqualToString:currentVersion]) {\n        [self purge];\n        [self createMetadata];\n        return;\n    }\n\n    // load infos\n    _metas = [NSMutableDictionary dictionaryWithDictionary:parsedObject];\n\n    _images = [NSMutableDictionary dictionaryWithDictionary:[_metas objectForKey:kFlyImageKeyImages]];\n    [_metas setObject:_images forKey:kFlyImageKeyImages];\n\n    NSString* fileName = [_metas objectForKey:kFlyImageKeyFile];\n    [self createDataFile:fileName];\n}\n\n- (void)createMetadata\n{\n    _metas = [NSMutableDictionary dictionaryWithCapacity:100];\n\n    // 记录当前版本号\n    NSString* currentVersion = [FlyImageUtils clientVersion];\n    if (currentVersion != nil) {\n        [_metas setObject:currentVersion forKey:kFlyImageKeyVersion];\n    }\n\n    // images\n    _images = [NSMutableDictionary dictionary];\n    [_metas setObject:_images forKey:kFlyImageKeyImages];\n\n    // file\n    NSString* fileName = [[NSUUID UUID] UUIDString];\n    [_metas setObject:fileName forKey:kFlyImageKeyFile];\n\n    [self createDataFile:fileName];\n}\n\n- (void)createDataFile:(NSString*)fileName\n{\n    _dataFile = [self.dataFileManager createFileWithName:fileName];\n    _dataFile.step = [FlyImageUtils pageSize] * 128; // 512KB\n    [_dataFile open];\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageRetrieveOperation.h",
    "content": "//\n//  FlyImageRetrieveOperation.h\n//  FlyImage\n//\n//  Created by Ye Tong on 8/11/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"FlyImageCacheProtocol.h\"\n\ntypedef UIImage* (^RetrieveOperationBlock)(void);\n\n/**\n *  Internal class. In charge of retrieving and sending UIImage.\n */\n@interface FlyImageRetrieveOperation : NSOperation\n\n/**\n *  When the operation start running, the block will be executed, \n *  and require an uncompressed UIImage.\n */\n- (instancetype)initWithRetrieveBlock:(RetrieveOperationBlock)block;\n\n/**\n *  Allow to add multiple blocks\n *\n *  @param block\n */\n- (void)addBlock:(FlyImageCacheRetrieveBlock)block;\n\n/**\n *  Callback with result image, which can be nil.\n */\n- (void)executeWithImage:(UIImage*)image;\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageRetrieveOperation.m",
    "content": "//\n//  FlyImageRetrieveOperation.m\n//  FlyImage\n//\n//  Created by Ye Tong on 8/11/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n//\n\n#import \"FlyImageRetrieveOperation.h\"\n\n@implementation FlyImageRetrieveOperation {\n    NSMutableArray* _blocks;\n    RetrieveOperationBlock _retrieveBlock;\n}\n\n- (instancetype)initWithRetrieveBlock:(RetrieveOperationBlock)block\n{\n    if (self = [self init]) {\n        _retrieveBlock = block;\n    }\n    return self;\n}\n\n- (void)addBlock:(FlyImageCacheRetrieveBlock)block\n{\n    if (_blocks == nil) {\n        _blocks = [NSMutableArray new];\n    }\n\n    [_blocks addObject:block];\n}\n\n- (void)executeWithImage:(UIImage*)image\n{\n    for (FlyImageCacheRetrieveBlock block in _blocks) {\n        block(self.name, image);\n    }\n    [_blocks removeAllObjects];\n}\n\n- (void)main\n{\n    if (self.isCancelled) {\n        return;\n    }\n\n    UIImage* image = _retrieveBlock();\n    [self executeWithImage:image];\n}\n\n- (void)cancel\n{\n    if (self.isFinished)\n        return;\n    [super cancel];\n\n    [self executeWithImage:nil];\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/Core/FlyImageUtils.h",
    "content": "//\n//  FlyImageUtils.h\n//  Demo\n//\n//  Created by Ye Tong on 3/18/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n#import <UIKit/UIKit.h>\n\ntypedef NS_ENUM(NSInteger, ImageContentType) { ImageContentTypeUnknown,\n                                               ImageContentTypeJPEG,\n                                               ImageContentTypePNG,\n                                               ImageContentTypeWebP,\n                                               ImageContentTypeGif,\n                                               ImageContentTypeTiff };\n\n@interface FlyImageUtils : NSObject\n\n+ (NSString*)directoryPath;\n\n+ (CGFloat)contentsScale;\n\n+ (NSString*)clientVersion;\n\n/**\n *  Memory page size, default is 4096\n */\n+ (int)pageSize;\n\n/**\n *  Compute the content type for an image data\n *\n *  @param data image data\n *\n */\n+ (ImageContentType)contentTypeForImageData:(NSData*)data;\n\n@end\n\n/**\n *  Copy from FastImageCache.\n *\n *  @param rect         draw area\n *  @param cornerRadius\n *\n */\nCGMutablePathRef _FICDCreateRoundedRectPath(CGRect rect, CGFloat cornerRadius);\n\n/**\n *  calculate drawing bounds with original image size, target size and contentsGravity of layer.\n *\n *  @param imageSize\n *  @param targetSize\n *  @param contentsGravity layer's attribute\n */\nCGRect _FlyImageCalcDrawBounds(CGSize imageSize, CGSize targetSize, NSString* const contentsGravity);\n\n#define FlyImageErrorLog(fmt, ...) NSLog((@\"FlyImage Error: \" fmt), ##__VA_ARGS__)\n\n#define dispatch_main_sync_safe(block)                   \\\n    if ([NSThread isMainThread]) {                       \\\n        block();                                         \\\n    } else {                                             \\\n        dispatch_sync(dispatch_get_main_queue(), block); \\\n    }\n\n#define dispatch_main_async_safe(block)                   \\\n    if ([NSThread isMainThread]) {                        \\\n        block();                                          \\\n    } else {                                              \\\n        dispatch_async(dispatch_get_main_queue(), block); \\\n    }\n"
  },
  {
    "path": "FlyImage/Core/FlyImageUtils.m",
    "content": "//\n//  FlyImageUtils.m\n//  Demo\n//\n//  Created by Ye Tong on 3/18/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"FlyImageUtils.h\"\n\n@implementation FlyImageUtils\n\n+ (NSString*)directoryPath\n{\n\n    static NSString* __directoryPath = nil;\n\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n\t\tNSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);\n\t\t__directoryPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@\"flyImage\"];\n\t\t\n\t\tNSFileManager *fileManager = [[NSFileManager alloc] init];\n\t\tBOOL directoryExists = [fileManager fileExistsAtPath:__directoryPath];\n\t\tif (directoryExists == NO) {\n\t\t\t[fileManager createDirectoryAtPath:__directoryPath withIntermediateDirectories:YES attributes:nil error:nil];\n\t\t}\n    });\n\n    return __directoryPath;\n}\n\n+ (CGFloat)contentsScale\n{\n\n    static CGFloat __contentsScale = 1;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n\t\t__contentsScale = [UIScreen mainScreen].scale;\n    });\n\n    return __contentsScale;\n}\n\n+ (NSString*)clientVersion\n{\n\n    static NSString* __clientVersion = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n\t\tNSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"];\n\t\tNSString *build = [[NSBundle mainBundle] infoDictionary][@\"CFBundleVersion\"];\n\t\t\n\t\t__clientVersion = [version stringByAppendingString:build];\n    });\n\n    return __clientVersion;\n}\n\n+ (int)pageSize\n{\n    static int __pageSize = 0;\n\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n\t\t__pageSize = getpagesize();\n    });\n\n    return __pageSize;\n}\n\n+ (ImageContentType)contentTypeForImageData:(NSData*)data\n{\n    uint8_t c;\n    [data getBytes:&c length:1];\n    switch (c) {\n    case 0xFF:\n        return ImageContentTypeJPEG;\n    case 0x89:\n        return ImageContentTypePNG;\n    case 0x47:\n        return ImageContentTypeGif;\n    case 0x49:\n    case 0x4D:\n        return ImageContentTypeTiff;\n    case 0x52:\n        // R as RIFF for WEBP\n        if ([data length] < 12) {\n            return ImageContentTypeUnknown;\n        }\n\n        NSString* testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];\n        if ([testString hasPrefix:@\"RIFF\"] && [testString hasSuffix:@\"WEBP\"]) {\n            return ImageContentTypeWebP;\n        }\n\n        return ImageContentTypeUnknown;\n    }\n    return ImageContentTypeUnknown;\n}\n\n// from FastImageCache\nCGMutablePathRef _FICDCreateRoundedRectPath(CGRect rect, CGFloat cornerRadius)\n{\n    CGMutablePathRef path = CGPathCreateMutable();\n\n    CGFloat minX = CGRectGetMinX(rect);\n    CGFloat midX = CGRectGetMidX(rect);\n    CGFloat maxX = CGRectGetMaxX(rect);\n    CGFloat minY = CGRectGetMinY(rect);\n    CGFloat midY = CGRectGetMidY(rect);\n    CGFloat maxY = CGRectGetMaxY(rect);\n\n    CGPathMoveToPoint(path, NULL, minX, midY);\n    CGPathAddArcToPoint(path, NULL, minX, maxY, midX, maxY, cornerRadius);\n    CGPathAddArcToPoint(path, NULL, maxX, maxY, maxX, midY, cornerRadius);\n    CGPathAddArcToPoint(path, NULL, maxX, minY, midX, minY, cornerRadius);\n    CGPathAddArcToPoint(path, NULL, minX, minY, minX, midY, cornerRadius);\n\n    return path;\n}\n\nCGRect _FlyImageCalcDrawBounds(CGSize imageSize, CGSize targetSize, NSString* const contentsGravity)\n{\n\n    CGFloat x, y, width, height;\n    if ([contentsGravity isEqualToString:kCAGravityCenter]) {\n\n        x = (targetSize.width - imageSize.width) / 2;\n        y = (targetSize.height - imageSize.height) / 2;\n        width = imageSize.width;\n        height = imageSize.height;\n\n    } else if ([contentsGravity isEqualToString:kCAGravityTop]) {\n\n        x = (targetSize.width - imageSize.width) / 2;\n        y = targetSize.height - imageSize.height;\n        width = imageSize.width;\n        height = imageSize.height;\n\n    } else if ([contentsGravity isEqualToString:kCAGravityBottom]) {\n\n        x = (targetSize.width - imageSize.width) / 2;\n        y = 0;\n        width = imageSize.width;\n        height = imageSize.height;\n\n    } else if ([contentsGravity isEqualToString:kCAGravityLeft]) {\n\n        x = 0;\n        y = (targetSize.height - imageSize.height) / 2;\n        width = imageSize.width;\n        height = imageSize.height;\n\n    } else if ([contentsGravity isEqualToString:kCAGravityRight]) {\n\n        x = targetSize.width - imageSize.width;\n        y = (targetSize.height - imageSize.height) / 2;\n        width = imageSize.width;\n        height = imageSize.height;\n\n    } else if ([contentsGravity isEqualToString:kCAGravityTopLeft]) {\n\n        x = 0;\n        y = targetSize.height - imageSize.height;\n        width = imageSize.width;\n        height = imageSize.height;\n\n    } else if ([contentsGravity isEqualToString:kCAGravityTopRight]) {\n\n        x = targetSize.width - imageSize.width;\n        y = targetSize.height - imageSize.height;\n        width = imageSize.width;\n        height = imageSize.height;\n\n    } else if ([contentsGravity isEqualToString:kCAGravityBottomLeft]) {\n\n        x = 0;\n        y = 0;\n        width = imageSize.width;\n        height = imageSize.height;\n\n    } else if ([contentsGravity isEqualToString:kCAGravityBottomRight]) {\n\n        x = targetSize.width - imageSize.width;\n        y = 0;\n        width = imageSize.width;\n        height = imageSize.height;\n\n    } else if ([contentsGravity isEqualToString:kCAGravityResizeAspectFill]) {\n\n        CGFloat scaleWidth = targetSize.width / imageSize.width;\n        CGFloat scaleHeight = targetSize.height / imageSize.height;\n\n        if (scaleWidth < scaleHeight) {\n            y = 0;\n            height = targetSize.height;\n            width = scaleHeight * imageSize.width;\n            x = (targetSize.width - width) / 2;\n        } else {\n            x = 0;\n            width = targetSize.width;\n            height = scaleWidth * imageSize.height;\n            y = (targetSize.height - height) / 2;\n        }\n    } else if ([contentsGravity isEqualToString:kCAGravityResize]) {\n\n        x = y = 0;\n        width = targetSize.width;\n        height = targetSize.height;\n\n    } else {\n\n        // kCAGravityResizeAspect\n        CGFloat scaleWidth = targetSize.width / imageSize.width;\n        CGFloat scaleHeight = targetSize.height / imageSize.height;\n\n        if (scaleWidth > scaleHeight) {\n            y = 0;\n            height = targetSize.height;\n            width = scaleHeight * imageSize.width;\n            x = (targetSize.width - width) / 2;\n        } else {\n            x = 0;\n            width = targetSize.width;\n            height = scaleWidth * imageSize.height;\n            y = (targetSize.height - height) / 2;\n        }\n    }\n\n    return CGRectMake(x, y, width, height);\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/FlyImage.h",
    "content": "//\n//  FlyImage.h\n//  FlyImage\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n//! Project version number for FlyImage.\nFOUNDATION_EXPORT double FlyImageVersionNumber;\n\n//! Project version string for FlyImage.\nFOUNDATION_EXPORT const unsigned char FlyImageVersionString[];\n\n#import <FlyImage/FlyImageDownloader.h>\n\n#import <FlyImage/FlyImageCacheProtocol.h>\n#import <FlyImage/FlyImageCache.h>\n#import <FlyImage/FlyImageIconCache.h>\n\n#import <FlyImage/FlyImageCacheUIProtocol.h>\n#import <FlyImage/CALayer+FlyImageCache.h>\n#import <FlyImage/UIImageView+FlyImageCache.h>\n\n#import <FlyImage/FlyImageIconCacheUIProtocol.h>\n#import <FlyImage/CALayer+FlyImageIconCache.h>\n#import <FlyImage/UIImageView+FlyImageIconCache.h>\n"
  },
  {
    "path": "FlyImage/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.flyimage.image</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>FMWK</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>NSPrincipalClass</key>\n\t<string></string>\n</dict>\n</plist>\n"
  },
  {
    "path": "FlyImage/UI/CALayer+FlyImageCache.h",
    "content": "//\n//  FlyImageLayer.h\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"FlyImageCacheUIProtocol.h\"\n\n@interface CALayer (FlyImageCache) <FlyImageCacheUIProtocol>\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/CALayer+FlyImageCache.m",
    "content": "//\n//  CALayer+FlyImageCache.m\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"CALayer+FlyImageCache.h\"\n#import \"FlyImageRenderer.h\"\n#import \"FlyImageUtils.h\"\n#import \"objc/runtime.h\"\n\n@interface CALayer (__FlyImageCache) <FlyImageRendererDelegate>\n@end\n\n@implementation CALayer (FlyImageCache)\n\nstatic char kRendererKey;\n\n- (void)setImageURL:(NSURL*)url\n{\n    [self setPlaceHolderImageName:nil thumbnailURL:nil originalURL:url];\n}\n\n- (void)setPlaceHolderImageName:(NSString*)imageName\n                   thumbnailURL:(NSURL*)thumbnailURL\n                    originalURL:(NSURL*)originalURL\n{\n    FlyImageRenderer* renderer = objc_getAssociatedObject(self, &kRendererKey);\n\n    if (renderer == nil) {\n        renderer = [[FlyImageRenderer alloc] init];\n        renderer.delegate = self;\n\n        self.contentsScale = [FlyImageUtils contentsScale];\n        self.drawsAsynchronously = YES;\n\n        objc_setAssociatedObject(self, &kRendererKey, renderer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n    }\n\n    [renderer setPlaceHolderImageName:imageName\n                         thumbnailURL:thumbnailURL\n                          originalURL:originalURL\n                             drawSize:self.bounds.size\n                      contentsGravity:self.contentsGravity\n                         cornerRadius:self.cornerRadius];\n}\n\n- (NSURL*)downloadingURL\n{\n    return objc_getAssociatedObject(self, @selector(downloadingURL));\n}\n\n- (void)setDownloadingURL:(NSURL*)url\n{\n    objc_setAssociatedObject(self, @selector(downloadingURL), url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n}\n\n- (float)downloadingPercentage\n{\n    return [objc_getAssociatedObject(self, @selector(downloadingPercentage)) floatValue];\n}\n\n- (void)setDownloadingPercentage:(float)progress\n{\n    objc_setAssociatedObject(self, @selector(downloadingPercentage), @(progress), OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n}\n\n#pragma mark - FlyImageRendererDelegate\n- (void)flyImageRenderer:(FlyImageRenderer*)render willRenderImage:(UIImage*)image\n{\n    if (image == nil && self.contents == nil) {\n        return;\n    }\n\n    [CATransaction begin];\n    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];\n    self.contents = (__bridge id _Nullable)(image.CGImage);\n    [CATransaction commit];\n\n    [self setNeedsLayout];\n}\n\n- (void)flyImageRenderer:(FlyImageRenderer*)render didDownloadImageURL:(NSURL*)url progress:(float)progress\n{\n    self.downloadingURL = url;\n    self.downloadingPercentage = progress;\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/CALayer+FlyImageIconCache.h",
    "content": "//\n//  CALayer+FlyImageIconCache.h\n//  FlyImage\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"FlyImageIconCacheUIProtocol.h\"\n\n@interface CALayer (FlyImageIconCache) <FlyImageIconCacheUIProtocol>\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/CALayer+FlyImageIconCache.m",
    "content": "//\n//  CALayer+FlyImageIconCache.m\n//  FlyImage\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n//\n\n#import \"CALayer+FlyImageIconCache.h\"\n#import \"FlyImageIconRenderer.h\"\n#import \"FlyImageUtils.h\"\n#import \"objc/runtime.h\"\n\n@interface CALayer (__FlyImageIconCache) <FlyImageIconRendererDelegate>\n@end\n\n@implementation CALayer (FlyImageIconCache)\n\nstatic char kRendererKey;\nstatic char kDrawingBlockKey;\n\n- (void)setIconURL:(NSURL*)iconURL\n{\n    [self setPlaceHolderImageName:nil iconURL:iconURL];\n}\n\n- (void)setPlaceHolderImageName:(NSString*)imageName\n                        iconURL:(NSURL*)iconURL\n{\n    FlyImageIconRenderer* renderer = objc_getAssociatedObject(self, &kRendererKey);\n\n    if (renderer == nil) {\n        renderer = [[FlyImageIconRenderer alloc] init];\n        renderer.delegate = self;\n\n        self.contentsScale = [FlyImageUtils contentsScale];\n        self.drawsAsynchronously = YES;\n\n        objc_setAssociatedObject(self, &kRendererKey, renderer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n    }\n\n    [renderer setPlaceHolderImageName:imageName\n                              iconURL:iconURL\n                             drawSize:self.bounds.size];\n}\n\n- (void)setIconDrawingBlock:(FlyImageIconDrawingBlock)block\n{\n    objc_setAssociatedObject(self, &kDrawingBlockKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n}\n\n- (void)drawImage:(UIImage*)image inContext:(CGContextRef)context bounds:(CGRect)contextBounds\n{\n    FlyImageIconDrawingBlock block = objc_getAssociatedObject(self, &kDrawingBlockKey);\n    if (block != nil) {\n        block(image, context, contextBounds);\n        return;\n    }\n\n    // Clip to a rounded rect\n    if (self.cornerRadius > 0) {\n        CGPathRef path = _FICDCreateRoundedRectPath(contextBounds, self.cornerRadius * [FlyImageUtils contentsScale]);\n        CGContextAddPath(context, path);\n        CFRelease(path);\n        CGContextEOClip(context);\n    }\n\n    UIGraphicsPushContext(context);\n    CGRect drawRect = _FlyImageCalcDrawBounds(image.size, contextBounds.size, self.contentsGravity);\n    [image drawInRect:drawRect];\n    UIGraphicsPopContext();\n}\n\n#pragma mark - FlyImageIconRendererDelegate\n- (void)flyImageIconRenderer:(FlyImageIconRenderer*)render\n                   drawImage:(UIImage*)image\n                     context:(CGContextRef)context\n                      bounds:(CGRect)contextBounds\n{\n    [self drawImage:image inContext:context bounds:contextBounds];\n}\n\n- (void)flyImageIconRenderer:(FlyImageIconRenderer*)render willRenderImage:(UIImage*)image\n{\n    if (image == nil && self.contents == nil) {\n        return;\n    }\n\n    [CATransaction begin];\n    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];\n    self.contents = (__bridge id _Nullable)(image.CGImage);\n    [CATransaction commit];\n\n    [self setNeedsLayout];\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/FlyImageCacheUIProtocol.h",
    "content": "//\n//  FlyImageCacheUIProtocol.h\n//  FlyImage\n//\n//  Created by Ye Tong on 8/9/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n//\n#import <UIKit/UIKit.h>\n\n@protocol FlyImageCacheUIProtocol <NSObject>\n\n@property (nonatomic, strong) NSURL* downloadingURL; // may be nil/thumbnailURL/originalURL.\n@property (nonatomic, assign) float downloadingPercentage; // 0-1, downloading progress per downloading URL.\n\n/**\n *  Convenient method of setPlaceHolderImageName:thumbnailURL:originalURL\n *\n *  @param url originalURL\n */\n- (void)setImageURL:(NSURL*)url;\n\n/**\n *  Download images and render them with the below order:\n *  1. PlaceHolder\n *  2. Thumbnail Image\n *  3. Original Image\n *\n *  These images will be saved into [FlyImageCache shareInstance]\n */\n- (void)setPlaceHolderImageName:(NSString*)imageName\n                   thumbnailURL:(NSURL*)thumbnailURL\n                    originalURL:(NSURL*)originalURL;\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/FlyImageIconCacheUIProtocol.h",
    "content": "//\n//  FlyImageIconCacheUIProtocol.h\n//  FlyImage\n//\n//  Created by Ye Tong on 8/9/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n//\n#import <UIKit/UIKit.h>\n\n/**\n *  Draw an image in the context with specific bounds.\n */\ntypedef void (^FlyImageIconDrawingBlock)(UIImage* image, CGContextRef context, CGRect contextBounds);\n\n@protocol FlyImageIconCacheUIProtocol <NSObject>\n\n/**\n *  Convenient method of setPlaceHolderImageName:iconURL.\n */\n- (void)setIconURL:(NSURL*)iconURL;\n\n/**\n *  Download an icon, and save it using [FlyImageIconCache shareInstance].\n */\n- (void)setPlaceHolderImageName:(NSString*)imageName\n                        iconURL:(NSURL*)iconURL;\n\n/**\n *  Set a customize drawing block. If not, it will use the default drawing method.\n */\n- (void)setIconDrawingBlock:(FlyImageIconDrawingBlock)block;\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/FlyImageIconRenderer.h",
    "content": "//\n//  FlyImageIconRenderer.h\n//  FlyImage\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"FlyImageIconCache.h\"\n\n@class FlyImageIconRenderer;\n@protocol FlyImageIconRendererDelegate <NSObject>\n\n- (void)flyImageIconRenderer:(FlyImageIconRenderer*)render willRenderImage:(UIImage*)image;\n\n- (void)flyImageIconRenderer:(FlyImageIconRenderer*)render\n                   drawImage:(UIImage*)image\n                     context:(CGContextRef)context\n                      bounds:(CGRect)contextBounds;\n\n@end\n\n/**\n *  Internal class to download, draw, and retrieve icons.\n */\n@interface FlyImageIconRenderer : NSObject\n\n@property (nonatomic, weak) id<FlyImageIconRendererDelegate> delegate;\n\n- (void)setPlaceHolderImageName:(NSString*)imageName\n                        iconURL:(NSURL*)iconURL\n                       drawSize:(CGSize)drawSize;\n\n@end"
  },
  {
    "path": "FlyImage/UI/FlyImageIconRenderer.m",
    "content": "//\n//  FlyImageIconRenderer.m\n//  FlyImage\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n//\n\n#import \"FlyImageIconRenderer.h\"\n#import \"FlyImageUtils.h\"\n#import \"FlyImageCache.h\"\n#import \"FlyImageDownloader.h\"\n\n@interface FlyImageIconRenderer ()\n@property (nonatomic, strong) NSURL* iconURL;\n@end\n\n@implementation FlyImageIconRenderer {\n    CGSize _drawSize;\n\n    FlyImageDownloadHandlerId* _downloadHandlerId;\n}\n\n- (void)dealloc\n{\n    [self cancelDownload];\n}\n\n- (void)cancelDownload\n{\n    if (_downloadHandlerId != nil) {\n        [[FlyImageDownloader sharedInstance] cancelDownloadHandler:_downloadHandlerId];\n        _downloadHandlerId = nil;\n    }\n}\n\n- (void)setPlaceHolderImageName:(NSString*)imageName\n                        iconURL:(NSURL*)iconURL\n                       drawSize:(CGSize)drawSize\n{\n\n    if (_iconURL != nil && [_iconURL.absoluteString isEqualToString:iconURL.absoluteString]) {\n        return;\n    }\n\n    [self cancelDownload];\n\n    _iconURL = iconURL;\n    _drawSize = CGSizeMake(round(drawSize.width), round(drawSize.height));\n\n    [self renderWithPlaceHolderImageName:imageName];\n}\n\n- (void)renderWithPlaceHolderImageName:(NSString*)imageName\n{\n    NSString* key = _iconURL.absoluteString;\n\n    // if has already downloaded image\n    if (key != nil && [[FlyImageIconCache sharedInstance] isImageExistWithKey:key]) {\n        __weak __typeof__(self) weakSelf = self;\n        [[FlyImageIconCache sharedInstance] asyncGetImageWithKey:key\n                                                       completed:^(NSString* key, UIImage* image) {\n\t\t\t[weakSelf renderImage:image key:key ];\n                                                       }];\n\n        return;\n    }\n\n    if (imageName != nil) {\n        UIImage* placeHolderImage = [UIImage imageNamed:imageName];\n        [self doRenderImage:placeHolderImage];\n    } else if (key != nil) {\n        // clear\n        [self doRenderImage:nil];\n    }\n\n    if (key == nil) {\n        return;\n    }\n\n    if ([[FlyImageCache sharedInstance] isImageExistWithKey:key]) {\n        NSString* imagePath = [[FlyImageCache sharedInstance] imagePathWithKey:key];\n        if (imagePath != nil) {\n            NSURL* url = [NSURL fileURLWithPath:imagePath];\n            [self drawIconWithKey:key url:url];\n            return;\n        }\n    }\n\n    [self downloadImage];\n}\n\n- (void)downloadImage\n{\n    __weak __typeof__(self) weakSelf = self;\n\n    NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:_iconURL];\n    request.timeoutInterval = 30; // Default 30 seconds\n    _downloadHandlerId = [[FlyImageDownloader sharedInstance]\n        downloadImageForURLRequest:request\n        success:^(NSURLRequest* request, NSURL* filePath) {\n\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t  NSString *downloadedKey = request.URL.absoluteString;\n\t\t\t\t\t\t\t  [[FlyImageCache sharedInstance] addImageWithKey:downloadedKey\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t filename:[filePath lastPathComponent]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcompleted:nil];\n\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t  // In case downloaded image is not equal with the new url\n\t\t\t\t\t\t\t  if ( ![downloadedKey isEqualToString:weakSelf.iconURL.absoluteString] ) {\n\t\t\t\t\t\t\t\t  return;\n\t\t\t\t\t\t\t  }\n\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t  _downloadHandlerId = nil;\n\t\t\t\t\t\t\t  [weakSelf drawIconWithKey:downloadedKey url:filePath];\n\n        }\n        failed:^(NSURLRequest* request, NSError* error) {\n\t\t\t\t\t\t\t  _downloadHandlerId = nil;\n        }];\n}\n\n- (void)drawIconWithKey:(NSString*)key url:(NSURL*)url\n{\n    __weak __typeof__(self) weakSelf = self;\n    [[FlyImageIconCache sharedInstance] addImageWithKey:key\n        size:_drawSize\n        drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t   \n\t\t\t\t\t\t\t\t\t\t\t   NSData *data = [NSData dataWithContentsOfURL:url];\n\t\t\t\t\t\t\t\t\t\t\t   UIImage *image = [UIImage imageWithData:data];\n\t\t\t\t\t\t\t\t\t\t\t   \n\t\t\t\t\t\t\t\t\t\t\t   [weakSelf.delegate flyImageIconRenderer:weakSelf\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t drawImage:image\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   context:context\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbounds:contextBounds];\n\n        }\n        completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t   [weakSelf renderImage:image key:key];\n        }];\n}\n\n- (void)renderImage:(UIImage*)image key:(NSString*)key\n{\n    dispatch_main_sync_safe(^{\n\t\tif ( ![_iconURL.absoluteString isEqualToString:key] ) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t[self doRenderImage:image];\n    });\n}\n\n- (void)doRenderImage:(UIImage*)image\n{\n    [_delegate flyImageIconRenderer:self willRenderImage:image];\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/FlyImageRenderer.h",
    "content": "//\n//  FlyImageRenderer.h\n//  Demo\n//\n//  Created by Norris Tong on 4/11/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@class FlyImageRenderer;\n@protocol FlyImageRendererDelegate <NSObject>\n\n/**\n *  Callback before download image.\n */\n- (void)flyImageRenderer:(FlyImageRenderer*)render willRenderImage:(UIImage*)image;\n\n@optional\n/**\n *  Callback after download image.\n *\n *  @param render\n *  @param url\n *  @param progress 0...1\n */\n- (void)flyImageRenderer:(FlyImageRenderer*)render didDownloadImageURL:(NSURL*)url progress:(float)progress;\n\n@end\n\n/**\n *  Internal class to download, draw, and retrieve images.\n */\n@interface FlyImageRenderer : NSObject\n\n@property (nonatomic, weak) id<FlyImageRendererDelegate> delegate;\n\n- (void)setPlaceHolderImageName:(NSString*)imageName\n                   thumbnailURL:(NSURL*)thumbnailURL\n                    originalURL:(NSURL*)originalURL\n                       drawSize:(CGSize)drawSize\n                contentsGravity:(NSString* const)contentsGravity\n                   cornerRadius:(CGFloat)cornerRadius;\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/FlyImageRenderer.m",
    "content": "//\n//  FlyImageRenderer.m\n//  Demo\n//\n//  Created by Norris Tong on 4/11/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"FlyImageRenderer.h\"\n#import \"FlyImageCache.h\"\n#import \"FlyImageUtils.h\"\n#import \"FlyImageDownloader.h\"\n\n@implementation FlyImageRenderer {\n    NSString* _placeHolderImageName;\n    NSURL* _thumbnailURL;\n    NSURL* _originalURL;\n\n    CGSize _drawSize;\n    NSString* _contentsGravity;\n    CGFloat _cornerRadius;\n\n    FlyImageDownloadHandlerId* _downloadHandlerId;\n}\n\n- (instancetype)init\n{\n    if (self = [super init]) {\n        // event\n        if ([FlyImageCache sharedInstance].autoDismissImage) {\n            [[NSNotificationCenter defaultCenter] addObserver:self\n                                                     selector:@selector(applicationWillEnterForeground:)\n                                                         name:UIApplicationWillEnterForegroundNotification\n                                                       object:nil];\n\n            [[NSNotificationCenter defaultCenter] addObserver:self\n                                                     selector:@selector(applicationDidEnterBackground:)\n                                                         name:UIApplicationDidEnterBackgroundNotification\n                                                       object:nil];\n        }\n    }\n    return self;\n}\n\n- (void)dealloc\n{\n    [self cancelDownload];\n\n    if ([FlyImageCache sharedInstance].autoDismissImage) {\n        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];\n        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];\n    }\n}\n\n- (void)applicationDidEnterBackground:(UIApplication*)application\n{\n    [self cancelDownload];\n\n    // clear image data to reduce memory\n    [self renderImage:nil];\n}\n\n- (void)applicationWillEnterForeground:(UIApplication*)application\n{\n    // repaint\n    [self render];\n}\n\n- (void)cancelDownload\n{\n    if (_downloadHandlerId != nil) {\n        [[FlyImageDownloader sharedInstance] cancelDownloadHandler:_downloadHandlerId];\n        _downloadHandlerId = nil;\n    }\n\n    // try to cancel getting image operation.\n    if (_originalURL) {\n        [[FlyImageCache sharedInstance] cancelGetImageWithKey:_originalURL.absoluteString];\n    }\n\n    if (_thumbnailURL) {\n        [[FlyImageCache sharedInstance] cancelGetImageWithKey:_thumbnailURL.absoluteString];\n    }\n}\n\n- (void)setPlaceHolderImageName:(NSString*)imageName\n                   thumbnailURL:(NSURL*)thumbnailURL\n                    originalURL:(NSURL*)originalURL\n                       drawSize:(CGSize)drawSize\n                contentsGravity:(NSString* const)contentsGravity\n                   cornerRadius:(CGFloat)cornerRadius\n{\n\n    if (_originalURL != nil && [_originalURL.absoluteString isEqualToString:originalURL.absoluteString]) {\n        return;\n    }\n\n    [self cancelDownload];\n\n    _placeHolderImageName = imageName;\n    _thumbnailURL = thumbnailURL;\n    _originalURL = originalURL;\n    _drawSize = drawSize;\n    _contentsGravity = contentsGravity;\n    _cornerRadius = cornerRadius;\n\n    [self render];\n}\n\n- (void)render\n{\n    // 0. clear\n    [self renderImage:nil];\n\n    // if has already downloaded original image\n    NSString* originalKey = _originalURL.absoluteString;\n    if (originalKey != nil && [[FlyImageCache sharedInstance] isImageExistWithKey:originalKey]) {\n        __weak __typeof__(self) weakSelf = self;\n        [[FlyImageCache sharedInstance] asyncGetImageWithKey:originalKey\n                                                    drawSize:_drawSize\n                                             contentsGravity:_contentsGravity\n                                                cornerRadius:_cornerRadius\n                                                   completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t[weakSelf renderOriginalImage:image key:key];\n                                                   }];\n        return;\n    }\n\n    // if there is no thumbnail, then render original image\n    NSString* thumbnailKey = _thumbnailURL.absoluteString;\n    if (thumbnailKey != nil && [[FlyImageCache sharedInstance] isImageExistWithKey:thumbnailKey]) {\n        __weak __typeof__(self) weakSelf = self;\n        [[FlyImageCache sharedInstance] asyncGetImageWithKey:thumbnailKey\n                                                    drawSize:_drawSize\n                                             contentsGravity:_contentsGravity\n                                                cornerRadius:_cornerRadius\n                                                   completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t[weakSelf renderThumbnailImage:image key:key];\n                                                   }];\n        return;\n    }\n\n    if (_placeHolderImageName != nil) {\n        UIImage* placeHolderImage = [UIImage imageNamed:_placeHolderImageName];\n        [self renderImage:placeHolderImage];\n    }\n\n    if (_thumbnailURL == nil && _originalURL != nil) {\n        [self downloadOriginal];\n        return;\n    }\n\n    if (_thumbnailURL == nil) {\n        return;\n    }\n\n    [self downloadThumbnail];\n}\n\n- (void)downloadThumbnail\n{\n\n    __weak __typeof__(self) weakSelf = self;\n    __block NSURL* downloadingURL = _thumbnailURL;\n    __block NSString* downloadingKey = downloadingURL.absoluteString;\n\n    NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:downloadingURL];\n    request.timeoutInterval = 30; // Default 30 seconds\n    _downloadHandlerId = [[FlyImageDownloader sharedInstance]\n        downloadImageForURLRequest:request\n        progress:^(float progress) {\n\t\t\t\t\t\t\t  if ( [_delegate respondsToSelector:@selector(flyImageRenderer:didDownloadImageURL:progress:)] ){\n\t\t\t\t\t\t\t\t  [_delegate flyImageRenderer:weakSelf didDownloadImageURL:downloadingURL progress:progress];\n\t\t\t\t\t\t\t  }\n        }\n        success:^(NSURLRequest* request, NSURL* filePath) {\n                              _downloadHandlerId = nil;\n                              \n                              [[FlyImageCache sharedInstance] addImageWithKey:downloadingKey\n                                                                     filename:filePath.lastPathComponent\n                                                                     drawSize:_drawSize\n                                                              contentsGravity:_contentsGravity\n                                                                 cornerRadius:_cornerRadius\n                                                                    completed:^(NSString *key, UIImage *image) {\n                                                                        [weakSelf renderThumbnailImage:image key:key];\n                                                                    }];\n\n        }\n        failed:^(NSURLRequest* request, NSError* error) {\n                              _downloadHandlerId = nil;\n\t\t\t\n\t\t\t\t\t\t\t  // if error code is cancelled, no need to download original image.\n                              if ( error.code != NSURLErrorCancelled && _originalURL != nil ){\n                                  [weakSelf downloadOriginal];\n                              }\n        }];\n}\n\n- (void)downloadOriginal\n{\n\n    __weak __typeof__(self) weakSelf = self;\n    __block NSURL* downloadingURL = _originalURL;\n    __block NSString* downloadingKey = downloadingURL.absoluteString;\n\n    NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:downloadingURL];\n    request.timeoutInterval = 30; // Default 30 seconds\n    _downloadHandlerId = [[FlyImageDownloader sharedInstance]\n        downloadImageForURLRequest:request\n        progress:^(float progress) {\n\t\t\t\t\t\t\t  if ( [_delegate respondsToSelector:@selector(flyImageRenderer:didDownloadImageURL:progress:)] ){\n\t\t\t\t\t\t\t\t  [_delegate flyImageRenderer:weakSelf didDownloadImageURL:downloadingURL progress:progress];\n\t\t\t\t\t\t\t  }\n        }\n        success:^(NSURLRequest* request, NSURL* filePath) {\n                              _downloadHandlerId = nil;\n                              \n                              [[FlyImageCache sharedInstance] addImageWithKey:downloadingKey\n                                                                     filename:filePath.lastPathComponent\n                                                                     drawSize:_drawSize\n                                                              contentsGravity:_contentsGravity\n                                                                 cornerRadius:_cornerRadius\n                                                                    completed:^(NSString *key, UIImage *image) {\n                                                                        [weakSelf renderOriginalImage:image key:key];\n                                                                    }];\n\n        }\n        failed:^(NSURLRequest* request, NSError* error) {\n                              _downloadHandlerId = nil;\n        }];\n}\n\n- (void)renderThumbnailImage:(UIImage*)image key:(NSString*)key\n{\n    dispatch_main_sync_safe(^{\n\t\tif ( ![key isEqualToString:_thumbnailURL.absoluteString] ) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t[self renderImage:image];\n\t\t\n\t\tif ( _originalURL != nil ){\n\t\t\t[self downloadOriginal];\n\t\t}\n    });\n}\n\n- (void)renderOriginalImage:(UIImage*)image key:(NSString*)key\n{\n    dispatch_main_sync_safe(^{\n\t\tif ( ![key isEqualToString:_originalURL.absoluteString] ) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t[self renderImage:image];\n    });\n}\n\n- (void)renderImage:(UIImage*)image\n{\n    [_delegate flyImageRenderer:self willRenderImage:image];\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/UIImageView+FlyImageCache.h",
    "content": "//\n//  UIImageView+FlyImageCache.h\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"FlyImageCacheUIProtocol.h\"\n\n@interface UIImageView (FlyImageCache) <FlyImageCacheUIProtocol>\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/UIImageView+FlyImageCache.m",
    "content": "//\n//  UIImageView+FlyImageCache.m\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import \"UIImageView+FlyImageCache.h\"\n#import \"FlyImageRenderer.h\"\n#import \"objc/runtime.h\"\n\n@interface UIImageView (__FlyImageCache) <FlyImageRendererDelegate>\n@end\n\n@implementation UIImageView (FlyImageCache)\n\nstatic char kRendererKey;\n\n- (void)setImageURL:(NSURL*)url\n{\n    [self setPlaceHolderImageName:nil thumbnailURL:nil originalURL:url];\n}\n\n- (void)setPlaceHolderImageName:(NSString*)imageName\n                   thumbnailURL:(NSURL*)thumbnailURL\n                    originalURL:(NSURL*)originalURL\n{\n    FlyImageRenderer* renderer = objc_getAssociatedObject(self, &kRendererKey);\n\n    if (renderer == nil) {\n        renderer = [[FlyImageRenderer alloc] init];\n        renderer.delegate = self;\n\n        objc_setAssociatedObject(self, &kRendererKey, renderer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n    }\n\n    [renderer setPlaceHolderImageName:imageName\n                         thumbnailURL:thumbnailURL\n                          originalURL:originalURL\n                             drawSize:self.bounds.size\n                      contentsGravity:self.layer.contentsGravity\n                         cornerRadius:self.layer.cornerRadius];\n}\n\n- (NSURL*)downloadingURL\n{\n    return objc_getAssociatedObject(self, @selector(downloadingURL));\n}\n\n- (void)setDownloadingURL:(NSURL*)url\n{\n    objc_setAssociatedObject(self, @selector(downloadingURL), url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n}\n\n- (float)downloadingPercentage\n{\n    return [objc_getAssociatedObject(self, @selector(downloadingPercentage)) floatValue];\n}\n\n- (void)setDownloadingPercentage:(float)progress\n{\n    objc_setAssociatedObject(self, @selector(downloadingPercentage), @(progress), OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n}\n\n#pragma mark - FlyImageRendererDelegate\n- (void)flyImageRenderer:(FlyImageRenderer*)render willRenderImage:(UIImage*)image\n{\n    if (image == nil && self.image == nil) {\n        return;\n    }\n\n    self.image = image;\n    [self setNeedsDisplay];\n}\n\n- (void)flyImageRenderer:(FlyImageRenderer*)render didDownloadImageURL:(NSURL*)url progress:(float)progress\n{\n    self.downloadingURL = url;\n    self.downloadingPercentage = progress;\n}\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/UIImageView+FlyImageIconCache.h",
    "content": "//\n//  UIImageView+FlyImageIconCache.h\n//  FlyImage\n//\n//  Created by Ye Tong on 5/3/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"FlyImageIconCacheUIProtocol.h\"\n\n@interface UIImageView (FlyImageIconCache) <FlyImageIconCacheUIProtocol>\n\n@end\n"
  },
  {
    "path": "FlyImage/UI/UIImageView+FlyImageIconCache.m",
    "content": "//\n//  UIImageView+FlyImageIconCache.m\n//  FlyImage\n//\n//  Created by Ye Tong on 5/3/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n//\n\n#import \"UIImageView+FlyImageIconCache.h\"\n#import \"FlyImageIconRenderer.h\"\n#import \"FlyImageUtils.h\"\n#import \"objc/runtime.h\"\n\n@interface UIImageView (__FlyImageIconCache) <FlyImageIconRendererDelegate>\n@end\n\n@implementation UIImageView (FlyImageIconCache)\n\nstatic char kRendererKey;\nstatic char kDrawingBlockKey;\n\n- (void)setIconURL:(NSURL*)iconURL\n{\n    [self setPlaceHolderImageName:nil iconURL:iconURL];\n}\n\n- (void)setPlaceHolderImageName:(NSString*)imageName\n                        iconURL:(NSURL*)iconURL\n{\n\n    FlyImageIconRenderer* renderer = objc_getAssociatedObject(self, &kRendererKey);\n\n    if (renderer == nil) {\n        renderer = [[FlyImageIconRenderer alloc] init];\n        renderer.delegate = self;\n\n        objc_setAssociatedObject(self, &kRendererKey, renderer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n    }\n\n    [renderer setPlaceHolderImageName:imageName\n                              iconURL:iconURL\n                             drawSize:self.bounds.size];\n}\n\n- (void)setIconDrawingBlock:(FlyImageIconDrawingBlock)block\n{\n    objc_setAssociatedObject(self, &kDrawingBlockKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n}\n\n- (void)drawImage:(UIImage*)image inContext:(CGContextRef)context bounds:(CGRect)contextBounds\n{\n    FlyImageIconDrawingBlock block = objc_getAssociatedObject(self, &kDrawingBlockKey);\n    if (block != nil) {\n        block(image, context, contextBounds);\n        return;\n    }\n\n    // Clip to a rounded rect\n    if (self.layer.cornerRadius > 0) {\n        CGPathRef path = _FICDCreateRoundedRectPath(contextBounds, self.layer.cornerRadius * [FlyImageUtils contentsScale]);\n        CGContextAddPath(context, path);\n        CFRelease(path);\n        CGContextEOClip(context);\n    }\n\n    UIGraphicsPushContext(context);\n    CGRect drawRect = _FlyImageCalcDrawBounds(image.size, contextBounds.size, self.layer.contentsGravity);\n    [image drawInRect:drawRect];\n    UIGraphicsPopContext();\n}\n\n#pragma mark - FlyImageIconRendererDelegate\n- (void)flyImageIconRenderer:(FlyImageIconRenderer*)render\n                   drawImage:(UIImage*)image\n                     context:(CGContextRef)context\n                      bounds:(CGRect)contextBounds\n{\n    [self drawImage:image inContext:context bounds:contextBounds];\n}\n\n- (void)flyImageIconRenderer:(FlyImageIconRenderer*)render willRenderImage:(UIImage*)image\n{\n    if (image == nil && self.image == nil) {\n        return;\n    }\n\n    self.image = image;\n    [self setNeedsLayout];\n}\n\n@end\n"
  },
  {
    "path": "FlyImage.podspec",
    "content": "Pod::Spec.new do |s|\n  s.name         = \"FlyImage\"\n  s.version      = \"1.1\"\n  s.summary      = \"Download, cache, render small images with UIImageView category\"\n  s.description  = \t'FlyImage takes the advantages of SDWebImage, FastImageCache and AFNetworking, '      \\\n  \t\t\t\t   \t'is a simple and high performance image library.Features: '      \\\n\t\t\t\t\t'High Performance, reduce memory operations while rendering, avoid Memory warning caused by image; ' \\\n\t\t\t\t\t'Store and retrieve different size of small images in one memory file, smooth scrolling; ' \\\n\t\t\t\t\t'Simple, support UIImageView, CALayer category; ' \\\n\t\t\t\t\t'An asynchronous image downloader; ' \\\n\t\t\t\t\t'Support WebP format; ' \\\n\t\t\t\t\t'Support mmap to improve I/O performace;'\n\n  s.homepage     = \"https://github.com/northwind/FlyImage\"\n  s.license      = \"MIT\"\n  s.author             = { \"norristong\" => \"norristong_x@qq.com\" }\n\n  s.platform     = :ios, \"8.0\"\n  s.source = { :git => 'https://github.com/northwind/FlyImage.git', :tag => s.version.to_s }\n  s.source_files  = \"FlyImage\", \"FlyImage/**/*.{h,m}\"\n\n  s.frameworks = \"ImageIO\", 'UIKit'\n  s.requires_arc = true\n  s.dependency 'AFNetworking', '~> 3.1'\n\n  s.default_subspec = 'Core'\n\n  s.subspec 'Core' do |core|\n    core.source_files = \"FlyImage\", 'FlyImage/**/*.{h,m}'\n  end\n\n  s.subspec 'WebP' do |webp|\n    webp.xcconfig = {\n      'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) FLYIMAGE_WEBP=1',\n      'USER_HEADER_SEARCH_PATHS' => '$(inherited) $(SRCROOT)/libwebp/src'\n    }\n    webp.watchos.xcconfig = {\n      'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) FLYIMAGE_WEBP=1',\n      'USER_HEADER_SEARCH_PATHS' => '$(inherited) $(SRCROOT)/libwebp/src'\n    }\n    webp.dependency 'FlyImage/Core'\n    webp.dependency 'libwebp'\n  end\n\nend\n"
  },
  {
    "path": "FlyImage.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t63D1D241E0B38FBE0700B2B2 /* libPods-FlyImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7D2BCD141491AB1301A46CC /* libPods-FlyImage.a */; };\n\t\tDD4D2C511D5C678E001F5D77 /* FlyImageRetrieveOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = DD4D2C4F1D5C678E001F5D77 /* FlyImageRetrieveOperation.h */; };\n\t\tDD4D2C521D5C678E001F5D77 /* FlyImageRetrieveOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4D2C501D5C678E001F5D77 /* FlyImageRetrieveOperation.m */; };\n\t\tDD4D2C531D5C678E001F5D77 /* FlyImageRetrieveOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = DD4D2C501D5C678E001F5D77 /* FlyImageRetrieveOperation.m */; };\n\t\tDD9D96E01CC50336008F279E /* FlyImage.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9D96DF1CC50336008F279E /* FlyImage.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\tDD9D96E71CC50336008F279E /* FlyImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD9D96DC1CC50336008F279E /* FlyImage.framework */; };\n\t\tDD9D97141CC5034A008F279E /* FlyImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9D96F71CC5034A008F279E /* FlyImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\tDD9D97151CC5034A008F279E /* FlyImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D96F81CC5034A008F279E /* FlyImageCache.m */; };\n\t\tDD9D97161CC5034A008F279E /* FlyImageCacheProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9D96F91CC5034A008F279E /* FlyImageCacheProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\tDD9D97171CC5034A008F279E /* FlyImageDataFile.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9D96FA1CC5034A008F279E /* FlyImageDataFile.h */; };\n\t\tDD9D97181CC5034A008F279E /* FlyImageDataFile.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D96FB1CC5034A008F279E /* FlyImageDataFile.m */; };\n\t\tDD9D97191CC5034A008F279E /* FlyImageDataFileManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9D96FC1CC5034A008F279E /* FlyImageDataFileManager.h */; };\n\t\tDD9D971A1CC5034A008F279E /* FlyImageDataFileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D96FD1CC5034A008F279E /* FlyImageDataFileManager.m */; };\n\t\tDD9D971B1CC5034A008F279E /* FlyImageDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9D96FE1CC5034A008F279E /* FlyImageDecoder.h */; };\n\t\tDD9D971C1CC5034A008F279E /* FlyImageDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D96FF1CC5034A008F279E /* FlyImageDecoder.m */; };\n\t\tDD9D971D1CC5034A008F279E /* FlyImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9D97001CC5034A008F279E /* FlyImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\tDD9D971E1CC5034A008F279E /* FlyImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D97011CC5034A008F279E /* FlyImageDownloader.m */; };\n\t\tDD9D971F1CC5034A008F279E /* FlyImageEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9D97021CC5034A008F279E /* FlyImageEncoder.h */; };\n\t\tDD9D97201CC5034A008F279E /* FlyImageEncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D97031CC5034A008F279E /* FlyImageEncoder.m */; };\n\t\tDD9D97211CC5034A008F279E /* FlyImageIconCache.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9D97041CC5034A008F279E /* FlyImageIconCache.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\tDD9D97221CC5034A008F279E /* FlyImageIconCache.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D97051CC5034A008F279E /* FlyImageIconCache.m */; };\n\t\tDD9D97231CC5034A008F279E /* FlyImageUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = DD9D97061CC5034A008F279E /* FlyImageUtils.h */; };\n\t\tDD9D97241CC5034A008F279E /* FlyImageUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D97071CC5034A008F279E /* FlyImageUtils.m */; };\n\t\tDD9D97341CC503A2008F279E /* FlyImageCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D972E1CC503A2008F279E /* FlyImageCacheTests.m */; };\n\t\tDD9D97351CC503A2008F279E /* FlyImageDataFileManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D972F1CC503A2008F279E /* FlyImageDataFileManagerTests.m */; };\n\t\tDD9D97361CC503A2008F279E /* FlyImageDataFileTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D97301CC503A2008F279E /* FlyImageDataFileTests.m */; };\n\t\tDD9D97371CC503A2008F279E /* FlyImageDownloadManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D97311CC503A2008F279E /* FlyImageDownloadManagerTests.m */; };\n\t\tDD9D97381CC503A2008F279E /* FlyImageIconCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D97321CC503A2008F279E /* FlyImageIconCacheTests.m */; };\n\t\tDDD8FB5B1D59D0F900821392 /* FlyImageIconCacheUIProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = DDD8FB5A1D59D0F900821392 /* FlyImageIconCacheUIProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\tDDD8FB5E1D59D24900821392 /* FlyImageCacheUIProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = DDD8FB5D1D59D24900821392 /* FlyImageCacheUIProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\tDDDAE6AE1CE6E10C00B3CCCC /* CALayer+FlyImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = DDDAE6A21CE6E10C00B3CCCC /* CALayer+FlyImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\tDDDAE6AF1CE6E10C00B3CCCC /* CALayer+FlyImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDAE6A31CE6E10C00B3CCCC /* CALayer+FlyImageCache.m */; };\n\t\tDDDAE6B01CE6E10C00B3CCCC /* CALayer+FlyImageIconCache.h in Headers */ = {isa = PBXBuildFile; fileRef = DDDAE6A41CE6E10C00B3CCCC /* CALayer+FlyImageIconCache.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\tDDDAE6B11CE6E10C00B3CCCC /* CALayer+FlyImageIconCache.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDAE6A51CE6E10C00B3CCCC /* CALayer+FlyImageIconCache.m */; };\n\t\tDDDAE6B21CE6E10C00B3CCCC /* FlyImageIconRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = DDDAE6A61CE6E10C00B3CCCC /* FlyImageIconRenderer.h */; };\n\t\tDDDAE6B31CE6E10C00B3CCCC /* FlyImageIconRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDAE6A71CE6E10C00B3CCCC /* FlyImageIconRenderer.m */; };\n\t\tDDDAE6B41CE6E10C00B3CCCC /* FlyImageRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = DDDAE6A81CE6E10C00B3CCCC /* FlyImageRenderer.h */; };\n\t\tDDDAE6B51CE6E10C00B3CCCC /* FlyImageRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDAE6A91CE6E10C00B3CCCC /* FlyImageRenderer.m */; };\n\t\tDDDAE6B61CE6E10C00B3CCCC /* UIImageView+FlyImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = DDDAE6AA1CE6E10C00B3CCCC /* UIImageView+FlyImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\tDDDAE6B71CE6E10C00B3CCCC /* UIImageView+FlyImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDAE6AB1CE6E10C00B3CCCC /* UIImageView+FlyImageCache.m */; };\n\t\tDDDAE6B81CE6E10C00B3CCCC /* UIImageView+FlyImageIconCache.h in Headers */ = {isa = PBXBuildFile; fileRef = DDDAE6AC1CE6E10C00B3CCCC /* UIImageView+FlyImageIconCache.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\tDDDAE6B91CE6E10C00B3CCCC /* UIImageView+FlyImageIconCache.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDAE6AD1CE6E10C00B3CCCC /* UIImageView+FlyImageIconCache.m */; };\n\t\tDDF65B111CC70DE50066B12F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDF65B101CC70DE50066B12F /* UIKit.framework */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\tDD9D96E81CC50336008F279E /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = DD9D96D31CC50336008F279E /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = DD9D96DB1CC50336008F279E;\n\t\t\tremoteInfo = FlyImage;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t2054736E2EDA981DF80AD030 /* Pods-FlyImage.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-FlyImage.release.xcconfig\"; path = \"Pods/Target Support Files/Pods-FlyImage/Pods-FlyImage.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tC05497892C966A58859B6B98 /* Pods-FlyImage.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-FlyImage.debug.xcconfig\"; path = \"Pods/Target Support Files/Pods-FlyImage/Pods-FlyImage.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tDD4C0C911CCEF78700FF7E28 /* libwebp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libwebp.framework; path = \"../../../Library/Developer/Xcode/DerivedData/FlyImage-dsmditzgpqdvcjaeenutizhwdsdm/Build/Products/Debug-iphonesimulator/libwebp.framework\"; sourceTree = \"<group>\"; };\n\t\tDD4D2C4F1D5C678E001F5D77 /* FlyImageRetrieveOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FlyImageRetrieveOperation.h; path = FlyImage/Core/FlyImageRetrieveOperation.h; sourceTree = SOURCE_ROOT; };\n\t\tDD4D2C501D5C678E001F5D77 /* FlyImageRetrieveOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FlyImageRetrieveOperation.m; path = FlyImage/Core/FlyImageRetrieveOperation.m; sourceTree = SOURCE_ROOT; };\n\t\tDD9D96DC1CC50336008F279E /* FlyImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FlyImage.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tDD9D96DF1CC50336008F279E /* FlyImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FlyImage.h; sourceTree = \"<group>\"; };\n\t\tDD9D96E11CC50336008F279E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tDD9D96E61CC50336008F279E /* FlyImageTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FlyImageTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tDD9D96ED1CC50336008F279E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tDD9D96F71CC5034A008F279E /* FlyImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageCache.h; sourceTree = \"<group>\"; };\n\t\tDD9D96F81CC5034A008F279E /* FlyImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageCache.m; sourceTree = \"<group>\"; };\n\t\tDD9D96F91CC5034A008F279E /* FlyImageCacheProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageCacheProtocol.h; sourceTree = \"<group>\"; };\n\t\tDD9D96FA1CC5034A008F279E /* FlyImageDataFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageDataFile.h; sourceTree = \"<group>\"; };\n\t\tDD9D96FB1CC5034A008F279E /* FlyImageDataFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageDataFile.m; sourceTree = \"<group>\"; };\n\t\tDD9D96FC1CC5034A008F279E /* FlyImageDataFileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageDataFileManager.h; sourceTree = \"<group>\"; };\n\t\tDD9D96FD1CC5034A008F279E /* FlyImageDataFileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageDataFileManager.m; sourceTree = \"<group>\"; };\n\t\tDD9D96FE1CC5034A008F279E /* FlyImageDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageDecoder.h; sourceTree = \"<group>\"; };\n\t\tDD9D96FF1CC5034A008F279E /* FlyImageDecoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageDecoder.m; sourceTree = \"<group>\"; };\n\t\tDD9D97001CC5034A008F279E /* FlyImageDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageDownloader.h; sourceTree = \"<group>\"; };\n\t\tDD9D97011CC5034A008F279E /* FlyImageDownloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageDownloader.m; sourceTree = \"<group>\"; };\n\t\tDD9D97021CC5034A008F279E /* FlyImageEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageEncoder.h; sourceTree = \"<group>\"; };\n\t\tDD9D97031CC5034A008F279E /* FlyImageEncoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageEncoder.m; sourceTree = \"<group>\"; };\n\t\tDD9D97041CC5034A008F279E /* FlyImageIconCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageIconCache.h; sourceTree = \"<group>\"; };\n\t\tDD9D97051CC5034A008F279E /* FlyImageIconCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageIconCache.m; sourceTree = \"<group>\"; };\n\t\tDD9D97061CC5034A008F279E /* FlyImageUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageUtils.h; sourceTree = \"<group>\"; };\n\t\tDD9D97071CC5034A008F279E /* FlyImageUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageUtils.m; sourceTree = \"<group>\"; };\n\t\tDD9D972E1CC503A2008F279E /* FlyImageCacheTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageCacheTests.m; sourceTree = \"<group>\"; };\n\t\tDD9D972F1CC503A2008F279E /* FlyImageDataFileManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageDataFileManagerTests.m; sourceTree = \"<group>\"; };\n\t\tDD9D97301CC503A2008F279E /* FlyImageDataFileTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageDataFileTests.m; sourceTree = \"<group>\"; };\n\t\tDD9D97311CC503A2008F279E /* FlyImageDownloadManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageDownloadManagerTests.m; sourceTree = \"<group>\"; };\n\t\tDD9D97321CC503A2008F279E /* FlyImageIconCacheTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageIconCacheTests.m; sourceTree = \"<group>\"; };\n\t\tDDD8FB5A1D59D0F900821392 /* FlyImageIconCacheUIProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageIconCacheUIProtocol.h; sourceTree = \"<group>\"; };\n\t\tDDD8FB5D1D59D24900821392 /* FlyImageCacheUIProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageCacheUIProtocol.h; sourceTree = \"<group>\"; };\n\t\tDDDAE6A21CE6E10C00B3CCCC /* CALayer+FlyImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"CALayer+FlyImageCache.h\"; sourceTree = \"<group>\"; };\n\t\tDDDAE6A31CE6E10C00B3CCCC /* CALayer+FlyImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"CALayer+FlyImageCache.m\"; sourceTree = \"<group>\"; };\n\t\tDDDAE6A41CE6E10C00B3CCCC /* CALayer+FlyImageIconCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"CALayer+FlyImageIconCache.h\"; sourceTree = \"<group>\"; };\n\t\tDDDAE6A51CE6E10C00B3CCCC /* CALayer+FlyImageIconCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"CALayer+FlyImageIconCache.m\"; sourceTree = \"<group>\"; };\n\t\tDDDAE6A61CE6E10C00B3CCCC /* FlyImageIconRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageIconRenderer.h; sourceTree = \"<group>\"; };\n\t\tDDDAE6A71CE6E10C00B3CCCC /* FlyImageIconRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageIconRenderer.m; sourceTree = \"<group>\"; };\n\t\tDDDAE6A81CE6E10C00B3CCCC /* FlyImageRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageRenderer.h; sourceTree = \"<group>\"; };\n\t\tDDDAE6A91CE6E10C00B3CCCC /* FlyImageRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageRenderer.m; sourceTree = \"<group>\"; };\n\t\tDDDAE6AA1CE6E10C00B3CCCC /* UIImageView+FlyImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"UIImageView+FlyImageCache.h\"; sourceTree = \"<group>\"; };\n\t\tDDDAE6AB1CE6E10C00B3CCCC /* UIImageView+FlyImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"UIImageView+FlyImageCache.m\"; sourceTree = \"<group>\"; };\n\t\tDDDAE6AC1CE6E10C00B3CCCC /* UIImageView+FlyImageIconCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"UIImageView+FlyImageIconCache.h\"; sourceTree = \"<group>\"; };\n\t\tDDDAE6AD1CE6E10C00B3CCCC /* UIImageView+FlyImageIconCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"UIImageView+FlyImageIconCache.m\"; sourceTree = \"<group>\"; };\n\t\tDDF65B101CC70DE50066B12F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };\n\t\tE7D2BCD141491AB1301A46CC /* libPods-FlyImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = \"libPods-FlyImage.a\"; sourceTree = BUILT_PRODUCTS_DIR; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\tDD9D96D81CC50336008F279E /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDDF65B111CC70DE50066B12F /* UIKit.framework in Frameworks */,\n\t\t\t\t63D1D241E0B38FBE0700B2B2 /* libPods-FlyImage.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDD9D96E31CC50336008F279E /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDD9D96E71CC50336008F279E /* FlyImage.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\tDD9D96D21CC50336008F279E = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDD9D96DE1CC50336008F279E /* FlyImage */,\n\t\t\t\tDD9D96EA1CC50336008F279E /* FlyImageTests */,\n\t\t\t\tDD9D96DD1CC50336008F279E /* Products */,\n\t\t\t\tE115FD25013B3B36CF3058C3 /* Frameworks */,\n\t\t\t\tF9DB01F8FD4F9561A9D733F0 /* Pods */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDD9D96DD1CC50336008F279E /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDD9D96DC1CC50336008F279E /* FlyImage.framework */,\n\t\t\t\tDD9D96E61CC50336008F279E /* FlyImageTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDD9D96DE1CC50336008F279E /* FlyImage */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDD9D96F61CC5034A008F279E /* Core */,\n\t\t\t\tDDDAE6A11CE6E10C00B3CCCC /* UI */,\n\t\t\t\tDD9D96DF1CC50336008F279E /* FlyImage.h */,\n\t\t\t\tDD9D96E11CC50336008F279E /* Info.plist */,\n\t\t\t);\n\t\t\tpath = FlyImage;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDD9D96EA1CC50336008F279E /* FlyImageTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDD9D972E1CC503A2008F279E /* FlyImageCacheTests.m */,\n\t\t\t\tDD9D972F1CC503A2008F279E /* FlyImageDataFileManagerTests.m */,\n\t\t\t\tDD9D97301CC503A2008F279E /* FlyImageDataFileTests.m */,\n\t\t\t\tDD9D97311CC503A2008F279E /* FlyImageDownloadManagerTests.m */,\n\t\t\t\tDD9D97321CC503A2008F279E /* FlyImageIconCacheTests.m */,\n\t\t\t\tDD9D96ED1CC50336008F279E /* Info.plist */,\n\t\t\t);\n\t\t\tpath = FlyImageTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDD9D96F61CC5034A008F279E /* Core */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDD9D96F71CC5034A008F279E /* FlyImageCache.h */,\n\t\t\t\tDD9D96F81CC5034A008F279E /* FlyImageCache.m */,\n\t\t\t\tDD9D96F91CC5034A008F279E /* FlyImageCacheProtocol.h */,\n\t\t\t\tDD9D96FA1CC5034A008F279E /* FlyImageDataFile.h */,\n\t\t\t\tDD9D96FB1CC5034A008F279E /* FlyImageDataFile.m */,\n\t\t\t\tDD9D96FC1CC5034A008F279E /* FlyImageDataFileManager.h */,\n\t\t\t\tDD9D96FD1CC5034A008F279E /* FlyImageDataFileManager.m */,\n\t\t\t\tDD9D96FE1CC5034A008F279E /* FlyImageDecoder.h */,\n\t\t\t\tDD9D96FF1CC5034A008F279E /* FlyImageDecoder.m */,\n\t\t\t\tDD9D97001CC5034A008F279E /* FlyImageDownloader.h */,\n\t\t\t\tDD9D97011CC5034A008F279E /* FlyImageDownloader.m */,\n\t\t\t\tDD9D97021CC5034A008F279E /* FlyImageEncoder.h */,\n\t\t\t\tDD9D97031CC5034A008F279E /* FlyImageEncoder.m */,\n\t\t\t\tDD9D97041CC5034A008F279E /* FlyImageIconCache.h */,\n\t\t\t\tDD9D97051CC5034A008F279E /* FlyImageIconCache.m */,\n\t\t\t\tDD9D97061CC5034A008F279E /* FlyImageUtils.h */,\n\t\t\t\tDD9D97071CC5034A008F279E /* FlyImageUtils.m */,\n\t\t\t\tDD4D2C4F1D5C678E001F5D77 /* FlyImageRetrieveOperation.h */,\n\t\t\t\tDD4D2C501D5C678E001F5D77 /* FlyImageRetrieveOperation.m */,\n\t\t\t);\n\t\t\tname = Core;\n\t\t\tpath = core;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDDDAE6A11CE6E10C00B3CCCC /* UI */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDDDAE6A21CE6E10C00B3CCCC /* CALayer+FlyImageCache.h */,\n\t\t\t\tDDDAE6A31CE6E10C00B3CCCC /* CALayer+FlyImageCache.m */,\n\t\t\t\tDDDAE6A41CE6E10C00B3CCCC /* CALayer+FlyImageIconCache.h */,\n\t\t\t\tDDDAE6A51CE6E10C00B3CCCC /* CALayer+FlyImageIconCache.m */,\n\t\t\t\tDDDAE6A61CE6E10C00B3CCCC /* FlyImageIconRenderer.h */,\n\t\t\t\tDDDAE6A71CE6E10C00B3CCCC /* FlyImageIconRenderer.m */,\n\t\t\t\tDDDAE6A81CE6E10C00B3CCCC /* FlyImageRenderer.h */,\n\t\t\t\tDDDAE6A91CE6E10C00B3CCCC /* FlyImageRenderer.m */,\n\t\t\t\tDDDAE6AA1CE6E10C00B3CCCC /* UIImageView+FlyImageCache.h */,\n\t\t\t\tDDDAE6AB1CE6E10C00B3CCCC /* UIImageView+FlyImageCache.m */,\n\t\t\t\tDDDAE6AC1CE6E10C00B3CCCC /* UIImageView+FlyImageIconCache.h */,\n\t\t\t\tDDDAE6AD1CE6E10C00B3CCCC /* UIImageView+FlyImageIconCache.m */,\n\t\t\t\tDDD8FB5A1D59D0F900821392 /* FlyImageIconCacheUIProtocol.h */,\n\t\t\t\tDDD8FB5D1D59D24900821392 /* FlyImageCacheUIProtocol.h */,\n\t\t\t);\n\t\t\tpath = UI;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tE115FD25013B3B36CF3058C3 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDD4C0C911CCEF78700FF7E28 /* libwebp.framework */,\n\t\t\t\tDDF65B101CC70DE50066B12F /* UIKit.framework */,\n\t\t\t\tE7D2BCD141491AB1301A46CC /* libPods-FlyImage.a */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tF9DB01F8FD4F9561A9D733F0 /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tC05497892C966A58859B6B98 /* Pods-FlyImage.debug.xcconfig */,\n\t\t\t\t2054736E2EDA981DF80AD030 /* Pods-FlyImage.release.xcconfig */,\n\t\t\t);\n\t\t\tname = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXHeadersBuildPhase section */\n\t\tDD9D96D91CC50336008F279E /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDD9D97231CC5034A008F279E /* FlyImageUtils.h in Headers */,\n\t\t\t\tDD9D97141CC5034A008F279E /* FlyImageCache.h in Headers */,\n\t\t\t\tDD4D2C511D5C678E001F5D77 /* FlyImageRetrieveOperation.h in Headers */,\n\t\t\t\tDD9D971D1CC5034A008F279E /* FlyImageDownloader.h in Headers */,\n\t\t\t\tDD9D97211CC5034A008F279E /* FlyImageIconCache.h in Headers */,\n\t\t\t\tDDDAE6B01CE6E10C00B3CCCC /* CALayer+FlyImageIconCache.h in Headers */,\n\t\t\t\tDDD8FB5B1D59D0F900821392 /* FlyImageIconCacheUIProtocol.h in Headers */,\n\t\t\t\tDDDAE6B61CE6E10C00B3CCCC /* UIImageView+FlyImageCache.h in Headers */,\n\t\t\t\tDDDAE6B81CE6E10C00B3CCCC /* UIImageView+FlyImageIconCache.h in Headers */,\n\t\t\t\tDDDAE6AE1CE6E10C00B3CCCC /* CALayer+FlyImageCache.h in Headers */,\n\t\t\t\tDDD8FB5E1D59D24900821392 /* FlyImageCacheUIProtocol.h in Headers */,\n\t\t\t\tDD9D97191CC5034A008F279E /* FlyImageDataFileManager.h in Headers */,\n\t\t\t\tDDDAE6B21CE6E10C00B3CCCC /* FlyImageIconRenderer.h in Headers */,\n\t\t\t\tDDDAE6B41CE6E10C00B3CCCC /* FlyImageRenderer.h in Headers */,\n\t\t\t\tDD9D97161CC5034A008F279E /* FlyImageCacheProtocol.h in Headers */,\n\t\t\t\tDD9D97171CC5034A008F279E /* FlyImageDataFile.h in Headers */,\n\t\t\t\tDD9D971B1CC5034A008F279E /* FlyImageDecoder.h in Headers */,\n\t\t\t\tDD9D96E01CC50336008F279E /* FlyImage.h in Headers */,\n\t\t\t\tDD9D971F1CC5034A008F279E /* FlyImageEncoder.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXHeadersBuildPhase section */\n\n/* Begin PBXNativeTarget section */\n\t\tDD9D96DB1CC50336008F279E /* FlyImage */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = DD9D96F01CC50336008F279E /* Build configuration list for PBXNativeTarget \"FlyImage\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t682C7851251E962AD95E8BD5 /* [CP] Check Pods Manifest.lock */,\n\t\t\t\tDD9D96D71CC50336008F279E /* Sources */,\n\t\t\t\tDD9D96D81CC50336008F279E /* Frameworks */,\n\t\t\t\tDD9D96D91CC50336008F279E /* Headers */,\n\t\t\t\tDD9D96DA1CC50336008F279E /* Resources */,\n\t\t\t\t5B8B2D959E77A65AC0CAB76B /* [CP] Copy Pods Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = FlyImage;\n\t\t\tproductName = FlyImage;\n\t\t\tproductReference = DD9D96DC1CC50336008F279E /* FlyImage.framework */;\n\t\t\tproductType = \"com.apple.product-type.framework\";\n\t\t};\n\t\tDD9D96E51CC50336008F279E /* FlyImageTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = DD9D96F31CC50336008F279E /* Build configuration list for PBXNativeTarget \"FlyImageTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tDD9D96E21CC50336008F279E /* Sources */,\n\t\t\t\tDD9D96E31CC50336008F279E /* Frameworks */,\n\t\t\t\tDD9D96E41CC50336008F279E /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tDD9D96E91CC50336008F279E /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = FlyImageTests;\n\t\t\tproductName = FlyImageTests;\n\t\t\tproductReference = DD9D96E61CC50336008F279E /* FlyImageTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tDD9D96D31CC50336008F279E /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0830;\n\t\t\t\tORGANIZATIONNAME = Augmn;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\tDD9D96DB1CC50336008F279E = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t};\n\t\t\t\t\tDD9D96E51CC50336008F279E = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = DD9D96D61CC50336008F279E /* Build configuration list for PBXProject \"FlyImage\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = DD9D96D21CC50336008F279E;\n\t\t\tproductRefGroup = DD9D96DD1CC50336008F279E /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tDD9D96DB1CC50336008F279E /* FlyImage */,\n\t\t\t\tDD9D96E51CC50336008F279E /* FlyImageTests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\tDD9D96DA1CC50336008F279E /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDD9D96E41CC50336008F279E /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t5B8B2D959E77A65AC0CAB76B /* [CP] Copy Pods Resources */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Copy Pods Resources\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-FlyImage/Pods-FlyImage-resources.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t682C7851251E962AD95E8BD5 /* [CP] Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"[CP] Check Pods Manifest.lock\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_ROOT}/../Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [ $? != 0 ] ; then\\n    # print error to STDERR\\n    echo \\\"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\\" >&2\\n    exit 1\\nfi\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\tDD9D96D71CC50336008F279E /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDDDAE6B31CE6E10C00B3CCCC /* FlyImageIconRenderer.m in Sources */,\n\t\t\t\tDD9D971C1CC5034A008F279E /* FlyImageDecoder.m in Sources */,\n\t\t\t\tDD9D97241CC5034A008F279E /* FlyImageUtils.m in Sources */,\n\t\t\t\tDD9D97151CC5034A008F279E /* FlyImageCache.m in Sources */,\n\t\t\t\tDD9D971E1CC5034A008F279E /* FlyImageDownloader.m in Sources */,\n\t\t\t\tDD9D97181CC5034A008F279E /* FlyImageDataFile.m in Sources */,\n\t\t\t\tDDDAE6B71CE6E10C00B3CCCC /* UIImageView+FlyImageCache.m in Sources */,\n\t\t\t\tDDDAE6B51CE6E10C00B3CCCC /* FlyImageRenderer.m in Sources */,\n\t\t\t\tDD4D2C521D5C678E001F5D77 /* FlyImageRetrieveOperation.m in Sources */,\n\t\t\t\tDDDAE6B11CE6E10C00B3CCCC /* CALayer+FlyImageIconCache.m in Sources */,\n\t\t\t\tDD9D97201CC5034A008F279E /* FlyImageEncoder.m in Sources */,\n\t\t\t\tDDDAE6B91CE6E10C00B3CCCC /* UIImageView+FlyImageIconCache.m in Sources */,\n\t\t\t\tDD9D971A1CC5034A008F279E /* FlyImageDataFileManager.m in Sources */,\n\t\t\t\tDD9D97221CC5034A008F279E /* FlyImageIconCache.m in Sources */,\n\t\t\t\tDDDAE6AF1CE6E10C00B3CCCC /* CALayer+FlyImageCache.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDD9D96E21CC50336008F279E /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDD9D97341CC503A2008F279E /* FlyImageCacheTests.m in Sources */,\n\t\t\t\tDD9D97381CC503A2008F279E /* FlyImageIconCacheTests.m in Sources */,\n\t\t\t\tDD9D97361CC503A2008F279E /* FlyImageDataFileTests.m in Sources */,\n\t\t\t\tDD9D97351CC503A2008F279E /* FlyImageDataFileManagerTests.m in Sources */,\n\t\t\t\tDD9D97371CC503A2008F279E /* FlyImageDownloadManagerTests.m in Sources */,\n\t\t\t\tDD4D2C531D5C678E001F5D77 /* FlyImageRetrieveOperation.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\tDD9D96E91CC50336008F279E /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = DD9D96DB1CC50336008F279E /* FlyImage */;\n\t\t\ttargetProxy = DD9D96E81CC50336008F279E /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin XCBuildConfiguration section */\n\t\tDD9D96EE1CC50336008F279E /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDD9D96EF1CC50336008F279E /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDD9D96F11CC50336008F279E /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = C05497892C966A58859B6B98 /* Pods-FlyImage.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tINFOPLIST_FILE = FlyImage/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.flyimage.imagecache;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDD9D96F21CC50336008F279E /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 2054736E2EDA981DF80AD030 /* Pods-FlyImage.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tINFOPLIST_FILE = FlyImage/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.flyimage.imagecache;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDD9D96F41CC50336008F279E /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = FlyImageTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.flyimage.imagecache.FlyImageTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDD9D96F51CC50336008F279E /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = FlyImageTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.flyimage.imagecache.FlyImageTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\tDD9D96D61CC50336008F279E /* Build configuration list for PBXProject \"FlyImage\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDD9D96EE1CC50336008F279E /* Debug */,\n\t\t\t\tDD9D96EF1CC50336008F279E /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tDD9D96F01CC50336008F279E /* Build configuration list for PBXNativeTarget \"FlyImage\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDD9D96F11CC50336008F279E /* Debug */,\n\t\t\t\tDD9D96F21CC50336008F279E /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tDD9D96F31CC50336008F279E /* Build configuration list for PBXNativeTarget \"FlyImageTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDD9D96F41CC50336008F279E /* Debug */,\n\t\t\t\tDD9D96F51CC50336008F279E /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = DD9D96D31CC50336008F279E /* Project object */;\n}\n"
  },
  {
    "path": "FlyImage.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:FlyImage.xcodeproj\">\n   </FileRef>\n   <FileRef\n      location = \"group:Pods/Pods.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "FlyImage.xcworkspace/xcshareddata/xcschemes/FlyImage.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"DD9D96DB1CC50336008F279E\"\n               BuildableName = \"FlyImage.framework\"\n               BlueprintName = \"FlyImage\"\n               ReferencedContainer = \"container:FlyImage.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"DD9D96E51CC50336008F279E\"\n               BuildableName = \"FlyImageTests.xctest\"\n               BlueprintName = \"FlyImageTests\"\n               ReferencedContainer = \"container:FlyImage.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DD9D96DB1CC50336008F279E\"\n            BuildableName = \"FlyImage.framework\"\n            BlueprintName = \"FlyImage\"\n            ReferencedContainer = \"container:FlyImage.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DD9D96DB1CC50336008F279E\"\n            BuildableName = \"FlyImage.framework\"\n            BlueprintName = \"FlyImage\"\n            ReferencedContainer = \"container:FlyImage.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DD9D96DB1CC50336008F279E\"\n            BuildableName = \"FlyImage.framework\"\n            BlueprintName = \"FlyImage\"\n            ReferencedContainer = \"container:FlyImage.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "FlyImage.xcworkspace/xcshareddata/xcschemes/FlyImageTests.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"DD9D96E51CC50336008F279E\"\n               BuildableName = \"FlyImageTests.xctest\"\n               BlueprintName = \"FlyImageTests\"\n               ReferencedContainer = \"container:FlyImage.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "FlyImageTests/FlyImageCacheTests.m",
    "content": "//\n//  FlyImageCacheTests.m\n//  Demo\n//\n//  Created by Norris Tong on 4/3/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <XCTest/XCTest.h>\n#import \"FlyImageCache.h\"\n#import \"FlyImageDataFIleManager.h\"\n\n@interface FlyImageCacheTests : XCTestCase\n\n@end\n\nstatic FlyImageCache* _imageCache;\nstatic CGFloat imageWidth = 1920.0;\nstatic CGFloat imageHeight = 1200.0;\nstatic FlyImageDataFileManager* _fileManager;\nstatic int kMultipleTimes = 15;\n\n@implementation FlyImageCacheTests\n\n- (void)setUp\n{\n    [super setUp];\n    // Put setup code here. This method is called before the invocation of each test method in the class.\n    if (_imageCache == nil) {\n        _imageCache = [FlyImageCache sharedInstance];\n        _fileManager = [_imageCache valueForKey:@\"dataFileManager\"];\n    }\n}\n\n- (void)tearDown\n{\n    // Put teardown code here. This method is called after the invocation of each test method in the class.\n    [super tearDown];\n}\n\n- (void)addImageFile:(NSString*)name\n{\n    // generate an image with special size\n    CGRect rect = CGRectMake(0.0f, 0.0f, imageWidth, imageHeight);\n    UIGraphicsBeginImageContext(rect.size);\n    CGContextRef context = UIGraphicsGetCurrentContext();\n    CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);\n    CGContextFillRect(context, rect);\n    UIImage* image = UIGraphicsGetImageFromCurrentImageContext();\n    UIGraphicsEndImageContext();\n\n    NSData* imageData = UIImagePNGRepresentation(image);\n    NSString* directoryPath = [_fileManager folderPath];\n    NSString* imagePath = [directoryPath stringByAppendingPathComponent:name];\n    [imageData writeToFile:imagePath atomically:YES];\n\n    [_fileManager addExistFileName:name];\n}\n\n- (void)drawALineInContext:(CGContextRef)context rect:(CGRect)rect\n{\n    UIGraphicsPushContext(context);\n\n    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);\n    CGContextSetLineWidth(context, 10.0);\n    CGContextMoveToPoint(context, 0.0, 0.0);\n    CGContextAddLineToPoint(context, rect.size.width, rect.size.height);\n\n    UIGraphicsPopContext();\n}\n\n- (void)test10AddImage\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test10AddImage\"];\n\n    NSString* filename = @\"10\";\n    [self addImageFile:filename];\n\n    [_imageCache addImageWithKey:filename\n                        filename:filename\n                       completed:^(NSString* key, UIImage* image) {\n                           XCTAssert( image.size.width == imageWidth );\n                           XCTAssert( image.size.height == imageHeight );\n                           \n                           [expectation fulfill];\n                       }];\n\n    [self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test11AddMultipleTimes\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test11AddMultipleTimes\"];\n\n    NSString* filename = @\"11\";\n    [self addImageFile:filename];\n\n    __block int sum = 0;\n    for (int i = 0; i < kMultipleTimes; i++) {\n\n        [_imageCache addImageWithKey:filename\n                            filename:filename\n                           completed:^(NSString* key, UIImage* image) {\n                               XCTAssert( image.size.width == imageWidth );\n                               XCTAssert( image.size.height == imageHeight );\n                               \n                               sum++;\n                               if ( sum == kMultipleTimes ){\n                                   [expectation fulfill];\n                               }\n                           }];\n    }\n\n    [self waitForExpectationsWithTimeout:30 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test13AddMultipleKeys\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test13AddMultipleKeys\"];\n\n    __block int sum = 0;\n    for (int i = 1; i <= kMultipleTimes; i++) {\n\n        NSString* filename = [NSString stringWithFormat:@\"%d\", i];\n        [self addImageFile:filename];\n\n        [_imageCache addImageWithKey:filename\n                            filename:filename\n                           completed:^(NSString* key, UIImage* image) {\n                               XCTAssert( image.size.width == imageWidth );\n                               XCTAssert( image.size.height == imageHeight );\n                               \n                               sum++;\n                               if ( sum == kMultipleTimes ){\n                                   [expectation fulfill];\n                               }\n                           }];\n    }\n\n    [self waitForExpectationsWithTimeout:100 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test30AsyncGetImage\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test30AsyncGetImage\"];\n\n    [_imageCache asyncGetImageWithKey:@\"10\"\n                            completed:^(NSString* key, UIImage* image) {\n        XCTAssert( image.size.width == imageWidth );\n        XCTAssert( image.size.height == imageHeight );\n        \n        [expectation fulfill];\n                            }];\n\n    [self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test30AsyncGetImageMultipleTimes\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test30AsyncGetImageMultipleTimes\"];\n\n    NSString* filename = @\"10\";\n\n    __block int sum = 0;\n    for (int i = 0; i < kMultipleTimes; i++) {\n        [_imageCache asyncGetImageWithKey:filename\n                                 drawSize:CGSizeMake(500, 800)\n                          contentsGravity:kCAGravityResizeAspect\n                             cornerRadius:0\n                                completed:^(NSString* key, UIImage* image) {\n                               XCTAssert( image.size.width == 500 );\n                               XCTAssert( image.size.height == 800 );\n                               \n                               sum++;\n                               if ( sum == kMultipleTimes ){\n                                   [expectation fulfill];\n                               }\n                                }];\n    }\n\n    [self waitForExpectationsWithTimeout:30 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test50RemoveImage\n{\n    NSString* imageKey = @\"11\";\n    [_imageCache removeImageWithKey:imageKey];\n    XCTAssert(![_imageCache isImageExistWithKey:imageKey]);\n}\n\n- (void)test60ImagePath\n{\n    XCTAssert([_imageCache imagePathWithKey:@\"10\"] != nil);\n    XCTAssert([_imageCache imagePathWithKey:@\"11\"] == nil);\n}\n\n- (void)test80ChangeImageKey\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test80ChangeImageKey\"];\n\n    [_imageCache changeImageKey:@\"10\" newKey:@\"newKey\"];\n    XCTAssert(![_imageCache isImageExistWithKey:@\"10\"]);\n    XCTAssert([_imageCache isImageExistWithKey:@\"newKey\"]);\n\n    [_imageCache asyncGetImageWithKey:@\"newKey\" completed:^(NSString* key, UIImage* image) {\n        XCTAssert( image.size.width == imageWidth );\n        XCTAssert( image.size.height == imageHeight );\n        \n        [expectation fulfill];\n    }];\n\n    [self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test90Purge\n{\n    [_imageCache purge];\n    XCTAssert(![_imageCache isImageExistWithKey:@\"10\"]);\n}\n\n@end\n"
  },
  {
    "path": "FlyImageTests/FlyImageDataFileManagerTests.m",
    "content": "//\n//  FlyImageDataFileManagerTests.m\n//  Demo\n//\n//  Created by Norris Tong on 4/2/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <XCTest/XCTest.h>\n#import \"FlyImageDataFileManager.h\"\n\n@interface FlyImageDataFileManagerTests : XCTestCase\n\n@end\n\nstatic FlyImageDataFileManager* _fileManager;\n\n@implementation FlyImageDataFileManagerTests\n\n- (void)setUp\n{\n    [super setUp];\n    // Put setup code here. This method is called before the invocation of each test method in the class.\n\n    // Put setup code here. This method is called before the invocation of each test method in the class.\n    if (_fileManager == nil) {\n        NSString* directoryPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];\n        NSString* folderPath = [directoryPath stringByAppendingPathComponent:@\"flyimage2/files\"];\n\n        _fileManager = [[FlyImageDataFileManager alloc] initWithFolderPath:folderPath];\n    }\n}\n\n- (void)tearDown\n{\n    // Put teardown code here. This method is called after the invocation of each test method in the class.\n    [super tearDown];\n}\n\n- (void)test10Create\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test10Create\"];\n\n    [_fileManager asyncCreateFileWithName:@\"10\" completed:^(FlyImageDataFile* dataFile) {\n        XCTAssert( dataFile != nil );\n        [expectation fulfill];\n    }];\n\n    [self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test11CreateMultipleTimes\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test11CreateMultipleTimes\"];\n\n    __block int sum = 0;\n    for (int i = 0; i < 100; i++) {\n        [_fileManager asyncCreateFileWithName:@\"11\" completed:^(FlyImageDataFile* dataFile) {\n            XCTAssert( dataFile != nil );\n            \n            sum++;\n            if ( sum == 100 ){\n                [expectation fulfill];\n            }\n        }];\n    }\n\n    [self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test12CreateSameName\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test12CreateSameName\"];\n\n    [_fileManager asyncCreateFileWithName:@\"10\" completed:^(FlyImageDataFile* dataFile) {\n        XCTAssert( dataFile != nil );\n        [expectation fulfill];\n    }];\n\n    [self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test13CreateMultipleNames\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test13CreateMultipleNames\"];\n\n    __block int sum = 0;\n    for (int i = 1; i <= 100; i++) {\n        [_fileManager asyncCreateFileWithName:[NSString stringWithFormat:@\"%d\", i] completed:^(FlyImageDataFile* dataFile) {\n            XCTAssert( dataFile != nil );\n            \n            sum++;\n            if ( sum == 100 ){\n                [expectation fulfill];\n            }\n        }];\n    }\n\n    [self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test15SyncCreate\n{\n    id dataFile = [_fileManager createFileWithName:@\"100\"];\n    XCTAssert(dataFile != nil);\n}\n\n- (void)test20IsExist\n{\n    XCTAssert([_fileManager isFileExistWithName:@\"10\"]);\n    XCTAssert([_fileManager isFileExistWithName:@\"11\"]);\n\n    XCTAssert(![_fileManager isFileExistWithName:@\"NotExist\"]);\n}\n\n- (void)test30Retrieve\n{\n    FlyImageDataFile* file10 = [_fileManager retrieveFileWithName:@\"10\"];\n    XCTAssert(file10 != nil);\n\n    FlyImageDataFile* file11 = [_fileManager retrieveFileWithName:@\"11\"];\n    XCTAssert(file11 != nil);\n\n    FlyImageDataFile* fileNotExist = [_fileManager retrieveFileWithName:@\"NotExist\"];\n    XCTAssert(fileNotExist == nil);\n}\n\n- (void)test50Remove\n{\n    [_fileManager removeFileWithName:@\"10\"];\n\n    XCTAssert(![_fileManager isFileExistWithName:@\"10\"]);\n}\n\n- (void)test90Purge\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test90Purge\"];\n\n    [_fileManager purgeWithExceptions:@[ @\"11\", @\"10\" ] toSize:0 completed:^(NSUInteger fileCount, NSUInteger totalSize) {\n        XCTAssert( fileCount > 0 );\n        XCTAssert( totalSize > 0 );\n        [expectation fulfill];\n    }];\n\n    [self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test99PurgeAll\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test99PurgeAll\"];\n\n    [_fileManager purgeWithExceptions:nil toSize:0 completed:^(NSUInteger fileCount, NSUInteger totalSize) {\n        XCTAssert( fileCount == 0 );\n        XCTAssert( totalSize == 0 );\n        [expectation fulfill];\n    }];\n\n    [self waitForExpectationsWithTimeout:1000 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n@end\n"
  },
  {
    "path": "FlyImageTests/FlyImageDataFileTests.m",
    "content": "//\n//  FlyImageDataFileTests.m\n//  Demo\n//\n//  Created by Norris Tong on 16/3/20.\n//  Copyright © 2016年 NorrisTong. All rights reserved.\n//\n\n#import <XCTest/XCTest.h>\n#import \"FlyImageDataFile.h\"\n#import \"FlyImageUtils.h\"\n#import <Metal/Metal.h>\n\n@interface FlyImageDataFileTests : XCTestCase\n\n@end\n\nstatic FlyImageDataFile* _dataFile;\nstatic size_t kTestLength = 4096 * 10;\nstatic int kTestCount = 50;\nstatic CGFloat imageWidth = 1920.0;\nstatic CGFloat imageHeight = 1200.0;\nstatic NSString* testDataFileName = @\"testDataFile\";\n\n@implementation FlyImageDataFileTests\n\n- (void)setUp\n{\n    [super setUp];\n\n    // Put setup code here. This method is called before the invocation of each test method in the class.\n    if (_dataFile == nil) {\n\n        NSString* filePath = [[FlyImageUtils directoryPath] stringByAppendingPathComponent:testDataFileName];\n        BOOL isFileExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];\n        if (!isFileExist) {\n            [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];\n        }\n\n        _dataFile = [[FlyImageDataFile alloc] initWithPath:filePath];\n    }\n}\n\n- (void)tearDown\n{\n    // Put teardown code here. This method is called after the invocation of each test method in the class.\n    [super tearDown];\n}\n\n- (void)test1Open\n{\n    XCTAssert([_dataFile open]);\n}\n\n- (void)test20PrepareAppendDataWrongLength\n{\n    XCTAssert(![_dataFile prepareAppendDataWithOffset:0 length:200 * 1024 * 1024]);\n}\n\n- (void)test30AppendData\n{\n    BOOL ret = YES;\n\n    for (int i = 0; i < kTestCount; i++) {\n        ret &= [_dataFile prepareAppendDataWithOffset:_dataFile.pointer length:kTestLength];\n        memset(_dataFile.address, 1, kTestLength);\n        ret &= [_dataFile appendDataWithOffset:_dataFile.pointer length:kTestLength];\n\n        if (!ret) {\n            break;\n        }\n    }\n\n    XCTAssert(ret, @\"Pass\");\n}\n\n- (void)createImageAtPath:(NSString*)path\n{\n    // generate an image with special size\n    CGRect rect = CGRectMake(0.0f, 0.0f, imageWidth, imageHeight);\n    UIGraphicsBeginImageContext(rect.size);\n    CGContextRef context = UIGraphicsGetCurrentContext();\n    CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);\n    CGContextFillRect(context, rect);\n    UIImage* image = UIGraphicsGetImageFromCurrentImageContext();\n    UIGraphicsEndImageContext();\n\n    NSData* imageData = UIImagePNGRepresentation(image);\n    [imageData writeToFile:path atomically:YES];\n}\n\n- (void)test50Memcpy\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"memcpy\"];\n\n    NSString* directoryPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];\n    NSString* imagePath = [directoryPath stringByAppendingPathComponent:@\"image\"];\n    [self createImageAtPath:imagePath];\n\n    NSData* data = [NSData dataWithContentsOfFile:imagePath];\n    UIImage* image = [UIImage imageWithData:data];\n    CGSize imageSize = image.size;\n\n    [data enumerateByteRangesUsingBlock:^(const void* _Nonnull bytes, NSRange byteRange, BOOL* _Nonnull stop) {\n\t\t\n\t\tsize_t length = byteRange.length;\n\t\tssize_t pageSize = [FlyImageUtils pageSize];\n\t\tsize_t correctLength = ceil((length / pageSize )) * pageSize;\n\t\t\n\t\tBOOL ret = YES;\n        ret &= [_dataFile prepareAppendDataWithOffset:0 length:correctLength];\n\t\tmemcpy(_dataFile.address, bytes, correctLength);\n        ret &= [_dataFile appendDataWithOffset:0 length:correctLength];\n\t\t\n\t\tXCTAssert( ret, @\"Pass\" );\n\t\t\n\t\t// Create CGImageRef whose backing store *is* the mapped image table entry. We avoid a memcpy this way.\n\t\tCGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, _dataFile.address, correctLength, nil);\n\t\t\n\t\tCGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;\n\t\tNSInteger bitsPerComponent = 8;\n\t\tNSInteger bitsPerPixel = 4 * 8;\n\t\tCGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();\n\t\t\n\t\tstatic NSInteger bytesPerPixel = 4;\n\t\tstatic float kAlignment = 64;\n\t\tsize_t bytesPerRow = ceil((imageSize.width * bytesPerPixel) / kAlignment) * kAlignment;\n\t\t\n\t\tCGImageRef imageRef = CGImageCreate(imageSize.width,\n\t\t\t\t\t\t\t\t\t\t\timageSize.height,\n\t\t\t\t\t\t\t\t\t\t\tbitsPerComponent,\n\t\t\t\t\t\t\t\t\t\t\tbitsPerPixel,\n\t\t\t\t\t\t\t\t\t\t\tbytesPerRow,\n\t\t\t\t\t\t\t\t\t\t\tcolorSpace,\n\t\t\t\t\t\t\t\t\t\t\tbitmapInfo,\n\t\t\t\t\t\t\t\t\t\t\tdataProvider,\n\t\t\t\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\t\t\t\t\t(CGColorRenderingIntent)0);\n\t\t\n\t\tCGDataProviderRelease(dataProvider);\n\t\tCGColorSpaceRelease(colorSpace);\n\t\t\n\t\tUIImage *revertImage = [UIImage imageWithCGImage:imageRef];\n\t\tXCTAssert( revertImage != nil, @\"Pass\" );\n\t\t\n\t\tCGSize revertSize = revertImage.size;\n\t\tXCTAssert( imageSize.width == revertSize.width && imageSize.height == imageSize.height, @\"Pass\" );\n\t\t\n\t\t[expectation fulfill];\n    }];\n\n    [self waitForExpectationsWithTimeout:10 handler:^(NSError* error) {\n        [[NSFileManager defaultManager] removeItemAtPath:imagePath error:nil];\n        \n        XCTAssert(YES, @\"Pass\");\n    }];\n}\n\n- (void)test99Remove\n{\n    [_dataFile close];\n    _dataFile = nil;\n\n    NSString* filePath = [[FlyImageUtils directoryPath] stringByAppendingPathComponent:testDataFileName];\n    [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];\n\n    XCTAssert(YES, @\"Pass\");\n}\n\n@end\n"
  },
  {
    "path": "FlyImageTests/FlyImageDownloadManagerTests.m",
    "content": "//\n//  FlyImageDownloaderTests.m\n//  Demo\n//\n//  Created by Norris Tong on 4/4/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <XCTest/XCTest.h>\n#import \"FlyImageDownloader.h\"\n\n@interface DownloadManagerClient : NSObject <FlyImageDownloaderDelegate>\n@property (nonatomic, strong) XCTestExpectation* expectation;\n@end\n\nstatic const NSString* kAssetHost = @\"https://flyimage.oss-us-west-1.aliyuncs.com/\";\nstatic int kMultipleTimes = 15;\n\n@implementation DownloadManagerClient\n- (void)FlyImageDownloader:(FlyImageDownloader*)manager\n           willSendRequest:(NSURLRequest*)request\n{\n    NSAssert(request != nil, nil);\n}\n\n- (void)FlyImageDownloader:(FlyImageDownloader*)manager\n        didReceiveResponse:(NSURLResponse*)response\n                  filePath:(NSURL*)filePath\n                     error:(NSError*)error\n                   request:(NSURLRequest*)request\n{\n    NSAssert(request != nil, nil);\n\n    [self.expectation fulfill];\n}\n\n- (void)FlyImageDownloader:(FlyImageDownloader*)manager\n         willCancelRequest:(NSURLRequest*)request\n{\n    NSAssert(request != nil, nil);\n\n    [self.expectation fulfill];\n}\n@end\n\n@interface FlyImageDownloaderTests : XCTestCase\n\n@end\n\nstatic FlyImageDownloader* _downloadManager;\n\n@implementation FlyImageDownloaderTests\n\n- (void)setUp\n{\n    [super setUp];\n    // Put setup code here. This method is called before the invocation of each test method in the class.\n    if (_downloadManager == nil) {\n        _downloadManager = [FlyImageDownloader sharedInstance];\n    }\n}\n\n- (void)tearDown\n{\n    // Put teardown code here. This method is called after the invocation of each test method in the class.\n    [super tearDown];\n\n    _downloadManager.delegate = nil;\n}\n\n- (void)test10Success\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test10AddImage\"];\n    NSString* imagePath = [kAssetHost stringByAppendingPathComponent:@\"10.jpg\"];\n\n    NSURL* url = [NSURL URLWithString:imagePath];\n    NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];\n    request.timeoutInterval = 30;\n    [_downloadManager downloadImageForURLRequest:request progress:^(float percentage) {\n        XCTAssert( percentage >= 0 && percentage <= 1 );\n    } success:^(NSURLRequest* request, NSURL* filePath) {\n        \n        NSData *data = [[NSData alloc] initWithContentsOfURL:filePath];\n        UIImage *image = [UIImage imageWithData:data];\n        XCTAssert( image.size.width == 1024 );\n        \n        [expectation fulfill];\n\n    } failed:^(NSURLRequest* request, NSError* error) {\n        XCTAssert( NO );\n        \n        [expectation fulfill];\n    }];\n\n    [self waitForExpectationsWithTimeout:60 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test30Failed\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test30Failed\"];\n    NSString* imagePath = [kAssetHost stringByAppendingPathComponent:@\"xxx\"];\n\n    NSURL* url = [NSURL URLWithString:imagePath];\n    NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];\n    request.timeoutInterval = 30;\n    [_downloadManager downloadImageForURLRequest:request progress:nil success:^(NSURLRequest* request, NSURL* filePath) {\n        XCTAssert( NO );\n        \n        [expectation fulfill];\n\n    } failed:^(NSURLRequest* request, NSError* error) {\n        XCTAssert( error != nil );\n        \n        [expectation fulfill];\n    }];\n\n    [self waitForExpectationsWithTimeout:60 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test31FailedMultiple\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test31FailedMultiple\"];\n    NSString* imagePath = [kAssetHost stringByAppendingPathComponent:@\"xxx\"];\n\n    __block int sum = 0;\n    for (int i = 0; i < kMultipleTimes; i++) {\n        NSURL* url = [NSURL URLWithString:imagePath];\n        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];\n        request.timeoutInterval = 5;\n        [_downloadManager downloadImageForURLRequest:request progress:nil success:^(NSURLRequest* request, NSURL* filePath) {\n            XCTAssert( NO );\n        } failed:^(NSURLRequest* request, NSError* error) {\n            XCTAssert( error != nil );\n            \n            sum++;\n            if ( sum == kMultipleTimes ){\n                [expectation fulfill];\n            }\n        }];\n    }\n\n    [self waitForExpectationsWithTimeout:60 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test50CancelTask\n{\n\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test90Cancel\"];\n    NSString* imagePath = [kAssetHost stringByAppendingPathComponent:@\"11.jpg\"];\n\n    NSURL* url = [NSURL URLWithString:imagePath];\n    NSURLRequest* request = [[NSURLRequest alloc] initWithURL:url];\n    FlyImageDownloadHandlerId* handlerId = [_downloadManager downloadImageForURLRequest:request\n        progress:nil\n        success:^(NSURLRequest* request, NSURL* filePath) {\n        XCTAssert( NO );\n        [expectation fulfill];\n        }\n        failed:^(NSURLRequest* request, NSError* error) {\n        XCTAssert( error != nil );\n        [expectation fulfill];\n        }];\n\n    [_downloadManager cancelDownloadHandler:handlerId];\n\n    [self waitForExpectationsWithTimeout:60 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test51CancelHandler\n{\n\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test91CancelMultipleTimes\"];\n    NSString* imagePath = [kAssetHost stringByAppendingPathComponent:@\"12.jpg\"];\n\n    NSURL* url = [NSURL URLWithString:imagePath];\n    NSURLRequest* request = [[NSURLRequest alloc] initWithURL:url];\n    FlyImageDownloadHandlerId* handlerId = [_downloadManager downloadImageForURLRequest:request\n        progress:nil\n        success:^(NSURLRequest* request, NSURL* filePath) {\n                                                                                    XCTAssert( NO );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t[expectation fulfill];\n        }\n        failed:^(NSURLRequest* request, NSError* error) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tXCTAssert( error != nil );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t[expectation fulfill];\n        }];\n\n    for (int i = 0; i < kMultipleTimes; i++) {\n        [_downloadManager downloadImageForURLRequest:request\n            progress:nil\n            success:^(NSURLRequest* request, NSURL* filePath) {\n\t\t\t\t\t\t\t\t\t\t\t\t XCTAssert( NO );\n\t\t\t\t\t\t\t\t\t\t\t\t [expectation fulfill];\n            }\n            failed:^(NSURLRequest* request, NSError* error) {\n                                                 XCTAssert( NO );\n                                                 [expectation fulfill];\n            }];\n    }\n\n    [_downloadManager cancelDownloadHandler:handlerId];\n\n    [self waitForExpectationsWithTimeout:60 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test90DelegateSend\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test50Delegate\"];\n\n    DownloadManagerClient* client = [[DownloadManagerClient alloc] init];\n    client.expectation = expectation;\n    _downloadManager.delegate = client;\n\n    NSString* imagePath = [kAssetHost stringByAppendingPathComponent:@\"13.jpg\"];\n    NSURL* url = [NSURL URLWithString:imagePath];\n    NSURLRequest* request = [[NSURLRequest alloc] initWithURL:url];\n    [_downloadManager downloadImageForURLRequest:request];\n\n    [self waitForExpectationsWithTimeout:60 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test91DelegateCancel\n{\n    XCTestExpectation* expectation = [self expectationWithDescription:@\"test50Delegate\"];\n\n    DownloadManagerClient* client = [[DownloadManagerClient alloc] init];\n    client.expectation = expectation;\n    _downloadManager.delegate = client;\n\n    NSString* imagePath = [kAssetHost stringByAppendingPathComponent:@\"14.jpg\"];\n    NSURL* url = [NSURL URLWithString:imagePath];\n    NSURLRequest* request = [[NSURLRequest alloc] initWithURL:url];\n    FlyImageDownloadHandlerId* handlerId = [_downloadManager downloadImageForURLRequest:request];\n    [_downloadManager cancelDownloadHandler:handlerId];\n\n    [self waitForExpectationsWithTimeout:60 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n@end\n"
  },
  {
    "path": "FlyImageTests/FlyImageIconCacheTests.m",
    "content": "//\n//  FlyImageIconCacheTests.m\n//  Demo\n//\n//  Created by Norris Tong on 4/3/16.\n//  Copyright © 2016 NorrisTong. All rights reserved.\n//\n\n#import <XCTest/XCTest.h>\n#import \"FlyImageIconCache.h\"\n\n@interface FlyImageIconCacheTests : XCTestCase\n\n@end\n\n#define kImageWidth 30\n#define kImageHeight 40\n\n@implementation FlyImageIconCacheTests\n\n- (void)setUp\n{\n\t[super setUp];\n\t// Put setup code here. This method is called before the invocation of each test method in the class.\n}\n\n- (void)tearDown\n{\n\t// Put teardown code here. This method is called after the invocation of each test method in the class.\n\t[super tearDown];\n}\n\n- (void)drawALineInContext:(CGContextRef)context rect:(CGRect)rect\n{\n\tUIGraphicsPushContext(context);\n\t\n\tCGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);\n\tCGContextSetLineWidth(context, 10.0);\n\tCGContextMoveToPoint(context, 0.0, 0.0);\n\tCGContextAddLineToPoint(context, rect.size.width, rect.size.height);\n\t\n\tUIGraphicsPopContext();\n}\n\n- (void)test10AddImage\n{\n\tXCTestExpectation* expectation = [self expectationWithDescription:@\"test10AddImage\"];\n\t\n\t[[FlyImageIconCache sharedInstance] addImageWithKey:@\"10\"\n\t\t\t\t\t\t\t\t\t\t\t\t   size:CGSizeMake(kImageWidth, kImageHeight)\n\t\t\t\t\t\t\t\t\t\t   drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t   [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t\t  completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.width == kImageWidth );\n\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.height == kImageHeight );\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t  [expectation fulfill];\n\t\t\t\t\t\t\t\t\t\t\t  }];\n\t\n\t[self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test11AddMultipleTimes\n{\n\tXCTestExpectation* expectation = [self expectationWithDescription:@\"test11AddMultipleTimes\"];\n\t\n\t__block int sum = 0;\n\tfor (int i = 0; i < 100; i++) {\n\t\t[[FlyImageIconCache sharedInstance] addImageWithKey:@\"11\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t   size:CGSizeMake(kImageWidth, kImageHeight)\n\t\t\t\t\t\t\t\t\t\t\t   drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t\t   [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t\t\t  completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.width == kImageWidth );\n\t\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.height == kImageHeight );\n\t\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t\t  sum++;\n\t\t\t\t\t\t\t\t\t\t\t\t\t  if ( sum == 100 ){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  [expectation fulfill];\n\t\t\t\t\t\t\t\t\t\t\t\t\t  }\n\t\t\t\t\t\t\t\t\t\t\t\t  }];\n\t}\n\t\n\t[self waitForExpectationsWithTimeout:30 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test12AddSameImage\n{\n\tXCTestExpectation* expectation = [self expectationWithDescription:@\"test12AddSameImage\"];\n\t\n\t[[FlyImageIconCache sharedInstance] addImageWithKey:@\"10\"\n\t\t\t\t\t\t\t\t\t\t\t\t   size:CGSizeMake(kImageWidth, kImageHeight)\n\t\t\t\t\t\t\t\t\t\t   drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t   [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t\t  completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t  [[FlyImageIconCache sharedInstance] addImageWithKey:@\"10\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t size:CGSizeMake(kImageWidth, kImageHeight)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcompleted:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tXCTAssert( image.size.width == kImageWidth );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tXCTAssert( image.size.height == kImageHeight );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t[expectation fulfill];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}];\n\t\t\t\t\t\t\t\t\t\t\t  }];\n\t\n\t[self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test13AddMultipleKeys\n{\n\tXCTestExpectation* expectation = [self expectationWithDescription:@\"test13AddMultipleKeys\"];\n\t\n\t__block int sum = 0;\n\tfor (int i = 1; i <= 100; i++) {\n\t\t[[FlyImageIconCache sharedInstance] addImageWithKey:[NSString stringWithFormat:@\"%d\", i]\n\t\t\t\t\t\t\t\t\t\t\t\t\t   size:CGSizeMake(kImageWidth, kImageHeight)\n\t\t\t\t\t\t\t\t\t\t\t   drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t\t   [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t\t\t  completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.width == kImageWidth );\n\t\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.height == kImageHeight );\n\t\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t\t  sum++;\n\t\t\t\t\t\t\t\t\t\t\t\t\t  if ( sum == 100 ){\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  [expectation fulfill];\n\t\t\t\t\t\t\t\t\t\t\t\t\t  }\n\t\t\t\t\t\t\t\t\t\t\t\t  }];\n\t}\n\t\n\t[self waitForExpectationsWithTimeout:30 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test20ReplaceImage\n{\n\tXCTestExpectation* expectation = [self expectationWithDescription:@\"test20ReplaceImage\"];\n\t\n\t[[FlyImageIconCache sharedInstance] addImageWithKey:@\"20\"\n\t\t\t\t\t\t\t\t\t\t\t\t   size:CGSizeMake(kImageWidth, kImageHeight)\n\t\t\t\t\t\t\t\t\t\t   drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t   [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t\t  completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t  [[FlyImageIconCache sharedInstance] replaceImageWithKey:@\"20\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcompleted:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tXCTAssert( image.size.width == kImageWidth );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tXCTAssert( image.size.height == kImageHeight );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t[expectation fulfill];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}];\n\t\t\t\t\t\t\t\t\t\t\t  }];\n\t\n\t[self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test30AsyncGetImage\n{\n\tXCTestExpectation* expectation = [self expectationWithDescription:@\"test30AsyncGetImage\"];\n\t\n\t[[FlyImageIconCache sharedInstance] addImageWithKey:@\"30\"\n\t\t\t\t\t\t\t\t\t\t\t\t   size:CGSizeMake(kImageWidth, kImageHeight)\n\t\t\t\t\t\t\t\t\t\t   drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t   [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t\t  completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t  [[FlyImageIconCache sharedInstance] asyncGetImageWithKey:@\"30\" completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.width == kImageWidth );\n\t\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.height == kImageHeight );\n\t\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t\t  [expectation fulfill];\n\t\t\t\t\t\t\t\t\t\t\t\t  }];\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t  }];\n\t\n\t[self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test31AsyncGetImageMultipleTimes\n{\n\tXCTestExpectation* expectation = [self expectationWithDescription:@\"test31AsyncGetImageMultipleTimes\"];\n\t\n\t[[FlyImageIconCache sharedInstance] addImageWithKey:@\"31\"\n\t\t\t\t\t\t\t\t\t\t\t\t   size:CGSizeMake(kImageWidth, kImageHeight)\n\t\t\t\t\t\t\t\t\t\t   drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t   [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t\t  completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t  __block int sum = 0;\n\t\t\t\t\t\t\t\t\t\t\t\t  for (int i = 0; i < 100; i++) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t  [[FlyImageIconCache sharedInstance] asyncGetImageWithKey:@\"31\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t completed:^(NSString* key, UIImage* image) {\n                           XCTAssert( image.size.width == kImageWidth );\n                           XCTAssert( image.size.height == kImageHeight );\n                           \n                           sum++;\n                           if ( sum == 100 ){\n\t\t\t\t\t\t\t   [expectation fulfill];\n\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t }];\n\t\t\t\t\t\t\t\t\t\t\t\t  }\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t  }];\n\t\n\t[self waitForExpectationsWithTimeout:30 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test40DifferentSize\n{\n\tXCTestExpectation* expectation = [self expectationWithDescription:@\"test40DifferentSize\"];\n\t\n\t[[FlyImageIconCache sharedInstance] addImageWithKey:@\"400\"\n\t\t\t\t\t\t\t\t\t\t\t\t   size:CGSizeMake(27, 57)\n\t\t\t\t\t\t\t\t\t\t   drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t   [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t\t  completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.width == 27 );\n\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.height == 57 );\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t  [[FlyImageIconCache sharedInstance] addImageWithKey:@\"401\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t size:CGSizeMake(88, 99)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcompleted:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tXCTAssert( image.size.width == 88 );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tXCTAssert( image.size.height == 99 );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t[expectation fulfill];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}];\n\t\t\t\t\t\t\t\t\t\t\t  }];\n\t\n\t[self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test70RemoveImage\n{\n\tXCTestExpectation* expectation = [self expectationWithDescription:@\"test70RemoveImage\"];\n\t\n\t[[FlyImageIconCache sharedInstance] addImageWithKey:@\"70\"\n\t\t\t\t\t\t\t\t\t\t\t\t   size:CGSizeMake(kImageWidth, kImageHeight)\n\t\t\t\t\t\t\t\t\t\t   drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t   [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t\t  completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t  [[FlyImageIconCache sharedInstance] removeImageWithKey:@\"70\"];\n\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert(![[FlyImageIconCache sharedInstance] isImageExistWithKey:@\"70\"]);\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t  [expectation fulfill];\n\t\t\t\t\t\t\t\t\t\t\t  }];\n\t\n\t[self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test80ChangeImageKey\n{\n\tXCTestExpectation* expectation = [self expectationWithDescription:@\"test80ChangeImageKey\"];\n\t\n\t[[FlyImageIconCache sharedInstance] addImageWithKey:@\"70\"\n\t\t\t\t\t\t\t\t\t\t\t\t   size:CGSizeMake(kImageWidth, kImageHeight)\n\t\t\t\t\t\t\t\t\t\t   drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n\t\t\t\t\t\t\t\t\t\t\t   [self drawALineInContext:context rect:contextBounds];\n\t\t\t\t\t\t\t\t\t\t   }\n\t\t\t\t\t\t\t\t\t\t\t  completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t  [[FlyImageIconCache sharedInstance] changeImageKey:@\"80\" newKey:@\"newKey\"];\n\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert(![[FlyImageIconCache sharedInstance] isImageExistWithKey:@\"80\"]);\n\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert([[FlyImageIconCache sharedInstance] isImageExistWithKey:@\"newKey\"]);\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t  [[FlyImageIconCache sharedInstance] asyncGetImageWithKey:@\"newKey\" completed:^(NSString* key, UIImage* image) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.width == kImageWidth );\n\t\t\t\t\t\t\t\t\t\t\t\t\t  XCTAssert( image.size.height == kImageHeight );\n\t\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t\t  [expectation fulfill];\n\t\t\t\t\t\t\t\t\t\t\t\t  }];\n\t\t\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t  }];\n\t\n\t[self waitForExpectationsWithTimeout:10 handler:^(NSError* error) { XCTAssert(YES, @\"Pass\"); }];\n}\n\n- (void)test90Purge\n{\n\t[[FlyImageIconCache sharedInstance] purge];\n\tXCTAssert(![[FlyImageIconCache sharedInstance] isImageExistWithKey:@\"10\"]);\n}\n\n@end\n"
  },
  {
    "path": "FlyImageTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2016 Olivier Poitrey rs@dailymotion.com\n \nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished\nto do so, subject to the following conditions:\n \nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n \nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n"
  },
  {
    "path": "Podfile",
    "content": "platform :ios, '8.0'\n\n# ignore all warnings from all pods\ninhibit_all_warnings!\n\ntarget \"FlyImage\" do\n  pod 'AFNetworking', '~> 3.1'\n\tpod 'libwebp', '0.6'\nend\n"
  },
  {
    "path": "README.md",
    "content": "![FlyImage Logo](Docs/logo.png) FlyImage\n=========\n[![Build Status](https://travis-ci.org/northwind/FlyImage.svg?branch=master)](https://travis-ci.org/northwind/FlyImage)\n[![Pod Version](http://img.shields.io/cocoapods/v/FlyImage.svg?style=flat)](http://cocoadocs.org/docsets/FlyImage/)\n[![Pod Platform](http://img.shields.io/cocoapods/p/FlyImage.svg?style=flat)](http://cocoadocs.org/docsets/FlyImage/)\n[![Pod License](http://img.shields.io/cocoapods/l/FlyImage.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0.html)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/northwind/FlyImage)\n\nFlyImage takes the advantages of [SDWebImage](https://github.com/rs/SDWebImage), [FastImageCache](https://github.com/path/FastImageCache) and [AFNetworking](https://github.com/AFNetworking/AFNetworking), is a simple and high performance image library. \n\nFeatures:\n\n- High Performance, reduce memory operations while rendering, avoid `Memory warning` caused by image\n- Store and retrieve different size of small images in one memory file, smooth scrolling\n- Simple, support `UIImageView`, `CALayer` category\n- An asynchronous image downloader\n- Support `WebP` format\n- Support `mmap` to improve I/O performace\n\n## Installation with CocoaPods\n\nSet the Podfile like this:\n\n```\nplatform :ios, '8.0'\npod 'FlyImage', '~>1.0'\n```\n\n\nIf you are using Swift, be sure to add `use_frameworks!`:\n\n```\nplatform :ios, '8.0'\nuse_frameworks!\npod 'FlyImage', '~>1.0'\n```\n\nIf you want to support `WebP`, just change the Podfile:\n\n```\nplatform :ios, '8.0'\npod 'FlyImage/WebP', '~>1.0'\n```\n\n## How To Use\n\nUsing UIImageView and CALayer Category\n\n```objective-c\n#import \"FlyImage.h\"\n...\n\nUIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];\n[imageView setPlaceHolderImageName:@\"default\"\n\t\t\t\t\t\tthumbnailURL:[NSURL urlWithString:@\"http://thumbnail\"]\n\t\t\t\t\t\toriginalURL:[NSURL urlWithString:@\"http://original\"]];\n[]self.view addSubview:imageView];\n...\n\nUIImageView *iconView = [[UIImageView alloc] initWithFrame:frame];\n[iconView setIconURL:[NSURL urlWithString:@\"http://original\"]];\n[]self.view addSubview:iconView];\n...\n\n```\n\nUsing FlyImageCache\n\n```objective-c\n// retrieve a specific key, and get callback\n[[FlyImageCache sharedInstance] asyncGetImageWithKey:key\n\t  \t\t\t\t\t\t\t\t\t   completed:^(NSString *key, UIImage *image) {\n\t\timageView.image = image;\n}];\n\n// remove a image from the cache\t\n[[FlyImageCache sharedInstance] removeImageWithKey:key];\n\n// delete all images\n[[FlyImageCache sharedInstance] purge];\n\n```\n\nUsing FlyImageIconCache\n\n```objective-c\n// add a new icon with a specific key\n[[FlyImageIconCache sharedInstance] addImageWithKey:key\n        size:drawSize\n        drawingBlock:^(CGContextRef context, CGRect contextBounds) {\n        \tUIImage *image = [UIImage imageWithName:@\"imageName\"];\n\n    \t\tUIGraphicsPushContext(context);\n\t\t    [image drawInRect:contextBounds];\n\t\t    UIGraphicsPopContext();\n        }\n        completed:nil];\n\n// retrieve a specific key, and get callback\n[[FlyImageCache sharedInstance] asyncGetImageWithKey:key\n\t  \t\t\t\t\t\t\t\t\t   completed:^(NSString *key, UIImage *image) {\n\t\timageView.image = image;\n}];\n\n```\n\nMore demos in folder [Examples](https://github.com/northwind/FlyImage/tree/master/Examples)\n\n\n## Performance Mesure\n\n\n#### Memory when scrolling images\n\n> Demo Target: FlyImageView / Device: iPhone6 Plus\n\nMemory | FlyImage | SDWebImage | UIKit\n------------ | ------------ | ------------- | ------------\nAll Heap Allocations | 2~7M | 2~4M  | 2~5M\nAll Anonymous VM | 17~30M | 310M  | 17~30M\n\n\n\n#### FPS when more than 170 small images in the same screen\n\n> Demo Target: FlyImageIconView / Device: iPhone6 Plus\n\nFlyImage | SDWebImage | UIKit\n------------ | ------------- | ------------\n58~60FPS | 6~7FPS  | 6~7FPS \n\n![FPS](Docs/iconcache.jpg)\n\n## Architecture\n![FlyImage Struct](Docs/classes.jpg)\n\n\n## License\n\nFlyImage is made available under the [MIT license](http://opensource.org/licenses/MIT)\n\n"
  }
]