Full Code of northwind/FlyImage for AI

master 08d2f5ccced4 cached
96 files
315.8 KB
87.6k tokens
3 symbols
1 requests
Download .txt
Showing preview only (342K chars total). Download the full file or copy to clipboard to get everything.
Repository: northwind/FlyImage
Branch: master
Commit: 08d2f5ccced4
Files: 96
Total size: 315.8 KB

Directory structure:
gitextract_2t9t0g8x/

├── .gitignore
├── .swift-version
├── .travis.yml
├── Examples/
│   ├── FlyImageIconView/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Info.plist
│   │   └── main.m
│   ├── FlyImageView/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Cells/
│   │   │   ├── BaseTableViewCell.h
│   │   │   ├── BaseTableViewCell.m
│   │   │   ├── FlyImageIconLayerTableViewCell.h
│   │   │   ├── FlyImageIconLayerTableViewCell.m
│   │   │   ├── FlyImageIconViewTableViewCell.h
│   │   │   ├── FlyImageIconViewTableViewCell.m
│   │   │   ├── FlyImageLayerTableViewCell.h
│   │   │   ├── FlyImageLayerTableViewCell.m
│   │   │   ├── FlyImageTableViewCell.h
│   │   │   ├── FlyImageTableViewCell.m
│   │   │   ├── SDWebImageTableViewCell.h
│   │   │   ├── SDWebImageTableViewCell.m
│   │   │   ├── TriditionTableViewCell.h
│   │   │   └── TriditionTableViewCell.m
│   │   ├── Info.plist
│   │   ├── Launch Screen.storyboard
│   │   ├── ProgressImageView.h
│   │   ├── ProgressImageView.m
│   │   ├── RootViewController.h
│   │   ├── RootViewController.m
│   │   └── main.m
│   ├── FlyImageView.xcodeproj/
│   │   └── project.pbxproj
│   ├── FlyImageView.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcshareddata/
│   │       └── xcschemes/
│   │           ├── FlyImageIconView.xcscheme
│   │           ├── FlyImageView.xcscheme
│   │           ├── SingleView.xcscheme
│   │           └── WebP.xcscheme
│   ├── Podfile
│   ├── SingleView/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Info.plist
│   │   ├── SingleViewController.h
│   │   ├── SingleViewController.m
│   │   └── main.m
│   └── WebP/
│       ├── AppDelegate.h
│       ├── AppDelegate.m
│       ├── Info.plist
│       └── main.m
├── FlyImage/
│   ├── Core/
│   │   ├── FlyImageCache.h
│   │   ├── FlyImageCache.m
│   │   ├── FlyImageCacheProtocol.h
│   │   ├── FlyImageDataFile.h
│   │   ├── FlyImageDataFile.m
│   │   ├── FlyImageDataFileManager.h
│   │   ├── FlyImageDataFileManager.m
│   │   ├── FlyImageDecoder.h
│   │   ├── FlyImageDecoder.m
│   │   ├── FlyImageDownloader.h
│   │   ├── FlyImageDownloader.m
│   │   ├── FlyImageEncoder.h
│   │   ├── FlyImageEncoder.m
│   │   ├── FlyImageIconCache.h
│   │   ├── FlyImageIconCache.m
│   │   ├── FlyImageRetrieveOperation.h
│   │   ├── FlyImageRetrieveOperation.m
│   │   ├── FlyImageUtils.h
│   │   └── FlyImageUtils.m
│   ├── FlyImage.h
│   ├── Info.plist
│   └── UI/
│       ├── CALayer+FlyImageCache.h
│       ├── CALayer+FlyImageCache.m
│       ├── CALayer+FlyImageIconCache.h
│       ├── CALayer+FlyImageIconCache.m
│       ├── FlyImageCacheUIProtocol.h
│       ├── FlyImageIconCacheUIProtocol.h
│       ├── FlyImageIconRenderer.h
│       ├── FlyImageIconRenderer.m
│       ├── FlyImageRenderer.h
│       ├── FlyImageRenderer.m
│       ├── UIImageView+FlyImageCache.h
│       ├── UIImageView+FlyImageCache.m
│       ├── UIImageView+FlyImageIconCache.h
│       └── UIImageView+FlyImageIconCache.m
├── FlyImage.podspec
├── FlyImage.xcodeproj/
│   └── project.pbxproj
├── FlyImage.xcworkspace/
│   ├── contents.xcworkspacedata
│   └── xcshareddata/
│       └── xcschemes/
│           ├── FlyImage.xcscheme
│           └── FlyImageTests.xcscheme
├── FlyImageTests/
│   ├── FlyImageCacheTests.m
│   ├── FlyImageDataFileManagerTests.m
│   ├── FlyImageDataFileTests.m
│   ├── FlyImageDownloadManagerTests.m
│   ├── FlyImageIconCacheTests.m
│   └── Info.plist
├── LICENSE
├── Podfile
└── README.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
project.xcworkspace
!default.xcworkspace
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
*.xcscmblueprint

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
Pods/
Podfile.lock


================================================
FILE: .swift-version
================================================
2.3


================================================
FILE: .travis.yml
================================================

language: objective-c

cache:
  - bundler
  - cocoapods

osx_image: xcode7.1

before_install:

    - export LANG=en_US.UTF-8
    - env
    - locale
    - gem install cocoapods --no-rdoc --no-ri --no-document --quiet
    - pod --version
    - pod setup --silent > /dev/null
    - pod repo update --silent
    
script:

    - pod lib lint --allow-warnings
    - xctool -workspace FlyImage.xcworkspace -scheme 'FlyImage' -sdk iphonesimulator -arch i386 build
    
    - pod install --project-directory=Examples    
    - xctool -workspace './Examples/FlyImageView.xcworkspace' -scheme 'FlyImageView' -sdk iphonesimulator -arch i386 build
    - xctool -workspace './Examples/FlyImageView.xcworkspace' -scheme 'FlyImageIconView' -sdk iphonesimulator -arch i386 build
    - xctool -workspace './Examples/FlyImageView.xcworkspace' -scheme 'WebP' -sdk iphonesimulator -arch i386 build
    - xctool -workspace './Examples/FlyImageView.xcworkspace' -scheme 'SingleView' -sdk iphonesimulator -arch i386 build
    
    - xcodebuild -workspace FlyImage.xcworkspace -scheme 'FlyImageTests' -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=latest' test
                

    

================================================
FILE: Examples/FlyImageIconView/AppDelegate.h
================================================
//
//  AppDelegate.h
//  FlyImageIconView
//
//  Created by Ye Tong on 4/27/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;


@end



================================================
FILE: Examples/FlyImageIconView/AppDelegate.m
================================================
//
//  AppDelegate.m
//  FlyImageIconView
//
//  Created by Ye Tong on 4/27/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import "AppDelegate.h"
#import "RootViewController.h"
#import "TriditionTableViewCell.h"
#import "SDWebImageTableViewCell.h"
#import "FlyImageIconLayerTableViewCell.h"
#import "FlyImageIconViewTableViewCell.h"
#import "FlyImage.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
	
	self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
	self.window.backgroundColor = [UIColor whiteColor];
	
	RootViewController *rootViewController = [[RootViewController alloc] init];
	rootViewController.suffix = @"_tn.jpg";
	rootViewController.cellsPerRow = 10;
	rootViewController.heightOfCell = self.window.bounds.size.width / rootViewController.cellsPerRow;
	rootViewController.activeIndex = 3;
	rootViewController.cells = @[ @{
									  @"class": [TriditionTableViewCell class],
									  @"title": @"UIKit"
									  },@{
									  @"class": [SDWebImageTableViewCell class],
									  @"title": @"SDWebImage"
									  }, @{
									  @"class": [FlyImageIconViewTableViewCell class],
									  @"title": @"FlyImageIconView"
									  }, @{
									  @"class": [FlyImageIconLayerTableViewCell class],
									  @"title": @"FlyImageIconLayer"
									  }];
	
	self.window.rootViewController = rootViewController;
	[self.window makeKeyAndVisible];
	
	return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
	// 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.
	// 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.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
	// 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.
	// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
	// 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.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
	// 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.
}

- (void)applicationWillTerminate:(UIApplication *)application {
	// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end


================================================
FILE: Examples/FlyImageIconView/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
	</dict>
	<key>UILaunchStoryboardName</key>
	<string>Launch Screen</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UIRequiresFullScreen</key>
	<true/>
	<key>UIStatusBarHidden</key>
	<true/>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
FILE: Examples/FlyImageIconView/main.m
================================================
//
//  main.m
//  FlyImageIconView
//
//  Created by Ye Tong on 4/27/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
	@autoreleasepool {
	    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
	}
}


================================================
FILE: Examples/FlyImageView/AppDelegate.h
================================================
//
//  AppDelegate.h
//  FlyImageView
//
//  Created by Ye Tong on 4/18/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;


@end



================================================
FILE: Examples/FlyImageView/AppDelegate.m
================================================
//
//  AppDelegate.m
//  FlyImageView
//
//  Created by Ye Tong on 4/18/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import "AppDelegate.h"
#import "RootViewController.h"
#import "TriditionTableViewCell.h"
#import "FlyImageTableViewCell.h"
#import "FlyImageLayerTableViewCell.h"
#import "SDWebImageTableViewCell.h"
#import "FlyImage.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
	self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
	self.window.backgroundColor = [UIColor whiteColor];
	
	[FlyImageCache sharedInstance].autoDismissImage = YES;
	
	RootViewController *rootViewController = [[RootViewController alloc] init];
	rootViewController.suffix = @".jpg";
	rootViewController.heightOfCell = 150;
	rootViewController.cellsPerRow = 1;
	rootViewController.activeIndex = 3;
	rootViewController.cells = @[ @{
									  @"class": [TriditionTableViewCell class],
									  @"title": @"UIKit"
									  },@{
									  @"class": [SDWebImageTableViewCell class],
									  @"title": @"SDWebImage"
									  } ,@{
									  @"class": [FlyImageTableViewCell class],
									  @"title": @"FlyImageView"
									  } ,@{
									  @"class": [FlyImageLayerTableViewCell class],
									  @"title": @"FlyImageLayer"
									  }];
	
	self.window.rootViewController = rootViewController;
	[self.window makeKeyAndVisible];
	
	return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
	// 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.
	// 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.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
	// 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.
	// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
	// 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.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
	// 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.
}

- (void)applicationWillTerminate:(UIApplication *)application {
	// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
	NSLog(@"Memory Warning");
}

@end


================================================
FILE: Examples/FlyImageView/Cells/BaseTableViewCell.h
================================================
//
//  BaseTableViewCell.h
//  Demo
//
//  Created by Norris Tong on 4/15/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface BaseTableViewCell : UITableViewCell

- (void)displayImageWithPhotos:(NSArray *)photos;

- (id)imageViewWithFrame:(CGRect)frame;

- (void)renderImageView:(id)imageView url:(NSURL *)url;

@end


================================================
FILE: Examples/FlyImageView/Cells/BaseTableViewCell.m
================================================
//
//  BaseTableViewCell.m
//  Demo
//
//  Created by Norris Tong on 4/15/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "BaseTableViewCell.h"

@implementation BaseTableViewCell {
    NSMutableArray *_imageViews;
    NSArray *_photos;
}

- (void)displayImageWithPhotos:(NSArray *)photos {
    
    if ( _imageViews == nil ) {
        NSInteger photoCount = [photos count];
        _imageViews = [[NSMutableArray alloc] initWithCapacity:photoCount];
        
        CGRect frame = self.frame;
        CGFloat itemWidth = floor(frame.size.width / photoCount);
        CGFloat padding = 2;
        for (int i=0; i<photoCount; i++) {
            id imageView = [self imageViewWithFrame:CGRectMake(i * itemWidth + padding, padding, itemWidth-padding*2, frame.size.height - padding*2)];
            [_imageViews addObject:imageView];
        }
    }
    
    _photos = photos;
    [self setNeedsLayout];
}

- (id)imageViewWithFrame:(CGRect)frame {
    return nil;
}

- (void)renderImageView:(id)imageView url:(NSURL *)url {
}

#pragma mark - Configuring the View Hierarchy
- (void)layoutSubviews {
    [super layoutSubviews];
    
    for (int i=0; i<MIN([_photos count], [_imageViews count]); i++) {
        id imageView = [_imageViews objectAtIndex:i];
        NSURL *url = [_photos objectAtIndex:i];
        [self renderImageView:imageView url:url];
    }
}

@end


================================================
FILE: Examples/FlyImageView/Cells/FlyImageIconLayerTableViewCell.h
================================================
//
//  FlyImageIconLayerTableViewCell.h
//  FlyImageView
//
//  Created by Ye Tong on 4/27/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import "BaseTableViewCell.h"

@interface FlyImageIconLayerTableViewCell : BaseTableViewCell

@end


================================================
FILE: Examples/FlyImageView/Cells/FlyImageIconLayerTableViewCell.m
================================================
//
//  FlyImageIconLayerTableViewCell.m
//  FlyImageView
//
//  Created by Ye Tong on 4/27/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import "FlyImageIconLayerTableViewCell.h"
#import "FlyImage.h"

@implementation FlyImageIconLayerTableViewCell

- (id)imageViewWithFrame:(CGRect)frame {
	CALayer *imageLayer = [[CALayer alloc] init];
	imageLayer.frame = frame;
	imageLayer.contentsGravity = kCAGravityResizeAspectFill;
	imageLayer.cornerRadius = 10;
	[self.layer addSublayer:imageLayer];
	
	return imageLayer;
}

- (void)renderImageView:(id)imageView url:(NSURL *)url {
	((CALayer *)imageView).iconURL = url;
}

@end


================================================
FILE: Examples/FlyImageView/Cells/FlyImageIconViewTableViewCell.h
================================================
//
//  FlyImageIconViewTableViewCell.h
//  FlyImageView
//
//  Created by Ye Tong on 5/3/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import "BaseTableViewCell.h"

@interface FlyImageIconViewTableViewCell : BaseTableViewCell

@end


================================================
FILE: Examples/FlyImageView/Cells/FlyImageIconViewTableViewCell.m
================================================
//
//  FlyImageIconViewTableViewCell.m
//  FlyImageView
//
//  Created by Ye Tong on 5/3/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import "FlyImageIconViewTableViewCell.h"
#import "FlyImage.h"

@implementation FlyImageIconViewTableViewCell

- (id)imageViewWithFrame:(CGRect)frame {
	UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
	imageView.contentMode = UIViewContentModeScaleAspectFill;
	imageView.layer.cornerRadius = 10;
	[self addSubview:imageView];
	
	return imageView;
}

- (void)renderImageView:(id)imageView url:(NSURL *)url {
	((UIImageView *)imageView).iconURL = url;
}

@end


================================================
FILE: Examples/FlyImageView/Cells/FlyImageLayerTableViewCell.h
================================================
//
//  FlyImageLayerTableViewCell.h
//  Demo
//
//  Created by Ye Tong on 4/18/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "BaseTableViewCell.h"

@interface FlyImageLayerTableViewCell : BaseTableViewCell

@end


================================================
FILE: Examples/FlyImageView/Cells/FlyImageLayerTableViewCell.m
================================================
//
//  FlyImageLayerTableViewCell.m
//  Demo
//
//  Created by Ye Tong on 4/18/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "FlyImageLayerTableViewCell.h"
#import "FlyImage.h"

@implementation FlyImageLayerTableViewCell

- (id)imageViewWithFrame:(CGRect)frame {
	CALayer *imageView = [[CALayer alloc] init];
	imageView.frame = frame;
	imageView.contentsGravity = kCAGravityResizeAspectFill;
	imageView.cornerRadius = 10;
	[self.layer addSublayer:imageView];
	
	return imageView;
}

- (void)renderImageView:(id)imageView url:(NSURL *)url {
	((CALayer *)imageView).imageURL = url;
}

@end


================================================
FILE: Examples/FlyImageView/Cells/FlyImageTableViewCell.h
================================================
//
//  FlyImageTableViewCell.h
//  Demo
//
//  Created by Norris Tong on 4/14/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "BaseTableViewCell.h"

@interface FlyImageTableViewCell : BaseTableViewCell

@end


================================================
FILE: Examples/FlyImageView/Cells/FlyImageTableViewCell.m
================================================
//
//  FlyImageTableViewCell.m
//  Demo
//
//  Created by Norris Tong on 4/14/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "FlyImageTableViewCell.h"
#import "FlyImage.h"
#import "ProgressImageView.h"

@implementation FlyImageTableViewCell

- (id)imageViewWithFrame:(CGRect)frame {
    ProgressImageView *imageView = [[ProgressImageView alloc] initWithFrame:frame];
    imageView.contentMode = UIViewContentModeScaleAspectFill;
    imageView.layer.cornerRadius = 10;
    [self addSubview:imageView];
	
    return imageView;
}

- (void)renderImageView:(id)imageView url:(NSURL *)url {
	[imageView setImageURL:url];
}

@end


================================================
FILE: Examples/FlyImageView/Cells/SDWebImageTableViewCell.h
================================================
//
//  SDWebImageTableViewCell.h
//  Demo
//
//  Created by Ye Tong on 4/18/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "BaseTableViewCell.h"

@interface SDWebImageTableViewCell : BaseTableViewCell

@end


================================================
FILE: Examples/FlyImageView/Cells/SDWebImageTableViewCell.m
================================================
//
//  SDWebImageTableViewCell.m
//  Demo
//
//  Created by Ye Tong on 4/18/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "SDWebImageTableViewCell.h"
#import "UIImageView+WebCache.h"

@implementation SDWebImageTableViewCell

- (id)imageViewWithFrame:(CGRect)frame {
	UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
	imageView.contentMode = UIViewContentModeScaleAspectFill;
	imageView.layer.cornerRadius = 10;
	[self addSubview:imageView];
	
	return imageView;
}

- (void)renderImageView:(id)imageView url:(NSURL *)url {
	[((UIImageView *)imageView) sd_setImageWithURL:url];
}

@end


================================================
FILE: Examples/FlyImageView/Cells/TriditionTableViewCell.h
================================================
//
//  TriditionTableViewCell.h
//  Demo
//
//  Created by Norris Tong on 4/14/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "BaseTableViewCell.h"

@interface TriditionTableViewCell : BaseTableViewCell

@end


================================================
FILE: Examples/FlyImageView/Cells/TriditionTableViewCell.m
================================================
//
//  TriditionTableViewCell.m
//  Demo
//
//  Created by Norris Tong on 4/14/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "TriditionTableViewCell.h"
#import "FlyImageDownloader.h"
#import "FlyImageDataFileManager.h"
#import "FlyImageCache.h"
#import <objc/runtime.h>
#import <CommonCrypto/CommonDigest.h>

@interface NSString (Extension)
- (NSString *)md5;
@end

@implementation NSString (Extension)
- (NSString *)md5 {
    const char *cStr = [self UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(cStr, (CC_LONG)strlen(cStr), result); // This is the md5 call
    return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
            result[0],
            result[1],
            result[2],
            result[3],
            result[4],
            result[5],
            result[6],
            result[7],
            result[8],
            result[9],
            result[10],
            result[11],
            result[12],
            result[13],
            result[14],
            result[15]];
}
@end

@implementation TriditionTableViewCell

- (id)imageViewWithFrame:(CGRect)frame {
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
    imageView.contentMode = UIViewContentModeScaleAspectFill;
    imageView.layer.masksToBounds = YES;
    imageView.layer.cornerRadius = 10;
    [self addSubview:imageView];
	
    return imageView;
}

- (void)renderImageView:(id)imageView url:(NSURL *)url {
	
	NSString *key = url.absoluteString;
    if ( [[FlyImageCache sharedInstance] isImageExistWithKey:key] ) {
		
		NSString *path = [[FlyImageCache sharedInstance] imagePathWithKey:key];
        NSURL *url = [NSURL fileURLWithPath:path];
        [self doRenderImageView:imageView url:url];
        
    }else{
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [[FlyImageDownloader sharedInstance] downloadImageForURLRequest:request progress:nil success:^(NSURLRequest *request, NSURL *filePath) {
            
            [[FlyImageCache sharedInstance] addImageWithKey:key filename:[filePath lastPathComponent] completed:^(NSString *key, UIImage *image) {
				((UIImageView *)imageView).image = image;
			}];
			
        } failed:^(NSURLRequest *request, NSError *error) {
            NSLog(@"occur error = %@", error );
        }];
		
		((UIImageView *)imageView).image = nil;
    }
}

- (void)doRenderImageView:(UIImageView *)imageView url:(NSURL *)url {
    NSData *data = [NSData dataWithContentsOfURL:url];
    UIImage *image = [UIImage imageWithData:data];
    imageView.image = image;
}

@end


================================================
FILE: Examples/FlyImageView/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
	</dict>
	<key>UILaunchStoryboardName</key>
	<string>Launch Screen</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UIRequiresFullScreen</key>
	<true/>
	<key>UIStatusBarHidden</key>
	<true/>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
FILE: Examples/FlyImageView/Launch Screen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
</document>


================================================
FILE: Examples/FlyImageView/ProgressImageView.h
================================================
//
//  ProgressImageView.h
//  FlyImageView
//
//  Created by Ye Tong on 8/12/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ProgressImageView : UIImageView

@end


================================================
FILE: Examples/FlyImageView/ProgressImageView.m
================================================
//
//  ProgressImageView.m
//  FlyImageView
//
//  Created by Ye Tong on 8/12/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import "ProgressImageView.h"
#import "FlyImage.h"

@implementation ProgressImageView

- (instancetype)initWithFrame:(CGRect)frame {
	if ( self = [super initWithFrame:frame] ) {
		[self addObserver:self forKeyPath:@"downloadingPercentage" options:NSKeyValueObservingOptionNew context:nil];
	}
	
	return self;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
	if ([keyPath isEqualToString:@"downloadingPercentage"]) {
		NSLog(@"downloadingURL : %@", self.downloadingURL );
		NSLog(@"downloadingPercentage : %f", self.downloadingPercentage );
	}
}

@end


================================================
FILE: Examples/FlyImageView/RootViewController.h
================================================
//
//  RootViewController.h
//  Demo
//
//  Created by Ye Tong on 3/24/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface RootViewController : UIViewController

@property (nonatomic, strong) NSArray *cells;
@property (nonatomic, assign) CGFloat heightOfCell;
@property (nonatomic, assign) NSInteger cellsPerRow;
@property (nonatomic, assign) NSInteger activeIndex;
@property (nonatomic, copy) NSString *suffix;

@end


================================================
FILE: Examples/FlyImageView/RootViewController.m
================================================
//
//  RootViewController.m
//  Demo
//
//  Created by Ye Tong on 3/24/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "RootViewController.h"
#import "BaseTableViewCell.h"
#import "SDImageCache.h"
#import <SDWebImageManager.h>

@interface RootViewController () <UITableViewDataSource, UITableViewDelegate, SDWebImageManagerDelegate>

@property (nonatomic, assign) CGFloat itemWidth;
@property (nonatomic, assign) CGFloat itemHeight;

@end

@implementation RootViewController {
	UITableView *_tableView;
	UISegmentedControl *_segment;
	
    NSMutableArray *_imageURLs;
    NSMutableArray *_cells;
    NSMutableArray *_indentifiers;
}

- (instancetype)init {
	if (self = [super init]) {
		_cells = [[NSMutableArray alloc] init];
		_indentifiers = [[NSMutableArray alloc] init];
		_activeIndex = 0;
	}
	return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
	self.view.backgroundColor = [UIColor whiteColor];
	
	// setup image paths
	_imageURLs = [[NSMutableArray alloc] init];
	for (int i=0; i<100; i++) {
		NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://flyimage.oss-us-west-1.aliyuncs.com/%d%@", i, self.suffix ]];
		[_imageURLs addObject:url];
	}
	
	CGFloat segmentHeight = 30;
	CGRect bounds = self.view.bounds;
	
	_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, bounds.size.width, bounds.size.height-segmentHeight)
											  style:UITableViewStylePlain];
	_tableView.opaque = YES;
	_tableView.directionalLockEnabled = YES;
	_tableView.backgroundColor = [UIColor clearColor];
	_tableView.allowsSelection = NO;
	_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
	_tableView.dataSource = self;
	_tableView.delegate = self;
	
	NSMutableArray *items = [NSMutableArray array];
	for (NSDictionary *info in _cells) {
		[items addObject: [info objectForKey:@"title"]];
		
		Class class = [info objectForKey:@"class"];
		NSString *indentifier = NSStringFromClass(class);
		[_indentifiers addObject:indentifier];
		[_tableView registerClass:class forCellReuseIdentifier:indentifier];
	}
	[self.view addSubview:_tableView];
	
	NSDictionary *textAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:10], NSFontAttributeName, nil];
	[[UISegmentedControl appearance] setTitleTextAttributes:textAttributes forState:UIControlStateNormal];
	
	_segment = [[UISegmentedControl alloc] initWithItems:items];
	_segment.backgroundColor = [UIColor whiteColor];
	_segment.frame = CGRectMake(0, bounds.size.height - segmentHeight, bounds.size.width, segmentHeight);
	[_segment setSelectedSegmentIndex:_activeIndex];
	[_segment addTarget:self action:@selector(onTapSegment) forControlEvents:UIControlEventValueChanged];
	[self.view addSubview:_segment];
    
    SDWebImageManager *sdManager = [SDWebImageManager sharedManager];
    sdManager.delegate = self;
    
    _itemWidth = floor(self.view.frame.size.width / _cellsPerRow) - 4;
    _itemHeight = _heightOfCell - 4;
}

#pragma mark - SDWebImageManagerDelegate

- (UIImage *)imageManager:(SDWebImageManager *)imageManager transformDownloadedImage:(UIImage *)image withURL:(NSURL *)imageURL{
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(_itemWidth, _heightOfCell), NO, [UIScreen mainScreen].scale);
    
    CGRect box = CGRectMake(0, 0, _itemWidth, _itemHeight);
    [[UIBezierPath bezierPathWithRoundedRect:box cornerRadius:10.f] addClip];
    [image drawInRect:box];
    
    UIImage* ret = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    return ret;
}

- (BOOL)prefersStatusBarHidden {
	return YES;
}

- (void)onTapSegment {
	_activeIndex = _segment.selectedSegmentIndex;
	
	[_tableView reloadData];
}

#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
	return 2000;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
	return self.heightOfCell;
}

// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	
    NSInteger startIndex = ([indexPath row] * self.cellsPerRow) % [_imageURLs count];
    NSInteger count = MIN(self.cellsPerRow, [_imageURLs count] - startIndex);
    NSArray *photos = [_imageURLs subarrayWithRange:NSMakeRange(startIndex, count)];
    
	BaseTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:_indentifiers[_activeIndex] forIndexPath:indexPath];
    [cell displayImageWithPhotos:photos];

    return cell;
}

@end


================================================
FILE: Examples/FlyImageView/main.m
================================================
//
//  main.m
//  FlyImageView
//
//  Created by Ye Tong on 4/18/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
	@autoreleasepool {
	    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
	}
}


================================================
FILE: Examples/FlyImageView.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		7539169AF2FD0C6CD1ED1213 /* libPods-FlyImageIconView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F9C3948F7DFDB6E2FE5F0B0 /* libPods-FlyImageIconView.a */; };
		8E45DB317D60C68FC813142D /* libPods-FlyImageView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DCBFE3EE450E44921AFAF53 /* libPods-FlyImageView.a */; };
		977F44737DA3E198C81BF6F4 /* libPods-SingleView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0280F6E421151FBFAE698C23 /* libPods-SingleView.a */; };
		CEE17C7A1B5057E6682927EF /* libPods-WebP.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EC1098E069AA6CA893D0F2C /* libPods-WebP.a */; };
		DD2EDB131D61E6C30085C9E3 /* ProgressImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8E088D1D5DD5BD00FEBC3A /* ProgressImageView.m */; };
		DD8E088E1D5DD5BD00FEBC3A /* ProgressImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = DD8E088D1D5DD5BD00FEBC3A /* ProgressImageView.m */; };
		DD9D97481CC5044D008F279E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D97471CC5044D008F279E /* main.m */; };
		DD9D974B1CC5044D008F279E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DD9D974A1CC5044D008F279E /* AppDelegate.m */; };
		DDBECFCD1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDBECFCC1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.m */; };
		DDBED17A1CD8C5D600EC9263 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DDBED1791CD8C5D600EC9263 /* main.m */; };
		DDBED17D1CD8C5D600EC9263 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DDBED17C1CD8C5D600EC9263 /* AppDelegate.m */; };
		DDBED19B1CD8C70C00EC9263 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1381CD0831F00EEC549 /* RootViewController.m */; };
		DDBED19C1CD8C71100EC9263 /* BaseTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F13C1CD0832400EEC549 /* BaseTableViewCell.m */; };
		DDBED19D1CD8C71900EC9263 /* TriditionTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1481CD0832400EEC549 /* TriditionTableViewCell.m */; };
		DDBED19E1CD8C71B00EC9263 /* SDWebImageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1461CD0832400EEC549 /* SDWebImageTableViewCell.m */; };
		DDBED19F1CD8C72A00EC9263 /* FlyImageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1441CD0832400EEC549 /* FlyImageTableViewCell.m */; };
		DDBED1A01CD8C72E00EC9263 /* FlyImageLayerTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1421CD0832400EEC549 /* FlyImageLayerTableViewCell.m */; };
		DDBED1A11CD8C76700EC9263 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDD1F1501CD083B300EEC549 /* Default-568h@2x.png */; };
		DDD1F1391CD0831F00EEC549 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1381CD0831F00EEC549 /* RootViewController.m */; };
		DDD1F1491CD0832400EEC549 /* BaseTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F13C1CD0832400EEC549 /* BaseTableViewCell.m */; };
		DDD1F14C1CD0832400EEC549 /* FlyImageLayerTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1421CD0832400EEC549 /* FlyImageLayerTableViewCell.m */; };
		DDD1F14D1CD0832400EEC549 /* FlyImageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1441CD0832400EEC549 /* FlyImageTableViewCell.m */; };
		DDD1F14E1CD0832400EEC549 /* SDWebImageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1461CD0832400EEC549 /* SDWebImageTableViewCell.m */; };
		DDD1F14F1CD0832400EEC549 /* TriditionTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1481CD0832400EEC549 /* TriditionTableViewCell.m */; };
		DDD1F1511CD083B300EEC549 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDD1F1501CD083B300EEC549 /* Default-568h@2x.png */; };
		DDD1F15A1CD084E500EEC549 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1591CD084E500EEC549 /* main.m */; };
		DDD1F15D1CD084E500EEC549 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F15C1CD084E500EEC549 /* AppDelegate.m */; };
		DDD1F18F1CD0872D00EEC549 /* BaseTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F13C1CD0832400EEC549 /* BaseTableViewCell.m */; };
		DDD1F1911CD0872D00EEC549 /* SDWebImageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1461CD0832400EEC549 /* SDWebImageTableViewCell.m */; };
		DDD1F1931CD0872D00EEC549 /* TriditionTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1481CD0832400EEC549 /* TriditionTableViewCell.m */; };
		DDD1F1941CD08D1E00EEC549 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F1381CD0831F00EEC549 /* RootViewController.m */; };
		DDD1F1951CD08E7D00EEC549 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDD1F1501CD083B300EEC549 /* Default-568h@2x.png */; };
		DDD1F1A01CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DDD1F19F1CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.m */; };
		DDD8FB601D59EB9200821392 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */; };
		DDD8FB611D59EB9200821392 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */; };
		DDD8FB621D59EB9200821392 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */; };
		DDD8FB631D59EB9200821392 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */; };
		DDDEF4321CE0AF4600C8366C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDEF4311CE0AF4600C8366C /* main.m */; };
		DDDEF4351CE0AF4600C8366C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDEF4341CE0AF4600C8366C /* AppDelegate.m */; };
		DDDEF4381CE0AF4600C8366C /* SingleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DDDEF4371CE0AF4600C8366C /* SingleViewController.m */; };
		DDDEF4451CE0B8AA00C8366C /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DDD1F1501CD083B300EEC549 /* Default-568h@2x.png */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
		0280F6E421151FBFAE698C23 /* libPods-SingleView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SingleView.a"; sourceTree = BUILT_PRODUCTS_DIR; };
		02F5D49EB862BEC96204662A /* 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>"; };
		33A4E8609F3283491E3DD133 /* 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>"; };
		3ABB5A3F814E3BFC95A513BD /* 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>"; };
		4EC1098E069AA6CA893D0F2C /* libPods-WebP.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-WebP.a"; sourceTree = BUILT_PRODUCTS_DIR; };
		5F9C3948F7DFDB6E2FE5F0B0 /* libPods-FlyImageIconView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-FlyImageIconView.a"; sourceTree = BUILT_PRODUCTS_DIR; };
		7D3083C3FEEB3316F9CCCF92 /* 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>"; };
		841CA4D45E6400A9646A0F66 /* 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>"; };
		9DCBFE3EE450E44921AFAF53 /* libPods-FlyImageView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-FlyImageView.a"; sourceTree = BUILT_PRODUCTS_DIR; };
		D95E1058D32716446EB3DC84 /* 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>"; };
		DD8E088C1D5DD5BD00FEBC3A /* ProgressImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgressImageView.h; path = ../ProgressImageView.h; sourceTree = "<group>"; };
		DD8E088D1D5DD5BD00FEBC3A /* ProgressImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ProgressImageView.m; path = ../ProgressImageView.m; sourceTree = "<group>"; };
		DD9D97431CC5044D008F279E /* FlyImageView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FlyImageView.app; sourceTree = BUILT_PRODUCTS_DIR; };
		DD9D97471CC5044D008F279E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
		DD9D97491CC5044D008F279E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
		DD9D974A1CC5044D008F279E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
		DD9D97571CC5044D008F279E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		DDBECFCB1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageIconViewTableViewCell.h; sourceTree = "<group>"; };
		DDBECFCC1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageIconViewTableViewCell.m; sourceTree = "<group>"; };
		DDBED1761CD8C5D600EC9263 /* WebP.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WebP.app; sourceTree = BUILT_PRODUCTS_DIR; };
		DDBED1791CD8C5D600EC9263 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
		DDBED17B1CD8C5D600EC9263 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
		DDBED17C1CD8C5D600EC9263 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
		DDBED1891CD8C5D600EC9263 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		DDD1F1371CD0831F00EEC549 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = "<group>"; };
		DDD1F1381CD0831F00EEC549 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = "<group>"; };
		DDD1F13B1CD0832400EEC549 /* BaseTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseTableViewCell.h; sourceTree = "<group>"; };
		DDD1F13C1CD0832400EEC549 /* BaseTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseTableViewCell.m; sourceTree = "<group>"; };
		DDD1F1411CD0832400EEC549 /* FlyImageLayerTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageLayerTableViewCell.h; sourceTree = "<group>"; };
		DDD1F1421CD0832400EEC549 /* FlyImageLayerTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageLayerTableViewCell.m; sourceTree = "<group>"; };
		DDD1F1431CD0832400EEC549 /* FlyImageTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageTableViewCell.h; sourceTree = "<group>"; };
		DDD1F1441CD0832400EEC549 /* FlyImageTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageTableViewCell.m; sourceTree = "<group>"; };
		DDD1F1451CD0832400EEC549 /* SDWebImageTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDWebImageTableViewCell.h; sourceTree = "<group>"; };
		DDD1F1461CD0832400EEC549 /* SDWebImageTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTableViewCell.m; sourceTree = "<group>"; };
		DDD1F1471CD0832400EEC549 /* TriditionTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TriditionTableViewCell.h; sourceTree = "<group>"; };
		DDD1F1481CD0832400EEC549 /* TriditionTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TriditionTableViewCell.m; sourceTree = "<group>"; };
		DDD1F1501CD083B300EEC549 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../Default-568h@2x.png"; sourceTree = "<group>"; };
		DDD1F1561CD084E500EEC549 /* FlyImageIconView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FlyImageIconView.app; sourceTree = BUILT_PRODUCTS_DIR; };
		DDD1F1591CD084E500EEC549 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
		DDD1F15B1CD084E500EEC549 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
		DDD1F15C1CD084E500EEC549 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
		DDD1F1691CD084E500EEC549 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		DDD1F19E1CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlyImageIconLayerTableViewCell.h; sourceTree = "<group>"; };
		DDD1F19F1CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlyImageIconLayerTableViewCell.m; sourceTree = "<group>"; };
		DDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
		DDDEF42E1CE0AF4600C8366C /* SingleView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SingleView.app; sourceTree = BUILT_PRODUCTS_DIR; };
		DDDEF4311CE0AF4600C8366C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
		DDDEF4331CE0AF4600C8366C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
		DDDEF4341CE0AF4600C8366C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
		DDDEF4361CE0AF4600C8366C /* SingleViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SingleViewController.h; sourceTree = "<group>"; };
		DDDEF4371CE0AF4600C8366C /* SingleViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SingleViewController.m; sourceTree = "<group>"; };
		DDDEF4411CE0AF4600C8366C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		E8620E15B0D1F42DDE6C37AA /* 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>"; };
		FF39DAB46C23D364F5631D94 /* 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>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		DD9D97401CC5044D008F279E /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				8E45DB317D60C68FC813142D /* libPods-FlyImageView.a in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		DDBED1731CD8C5D600EC9263 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				CEE17C7A1B5057E6682927EF /* libPods-WebP.a in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		DDD1F1531CD084E500EEC549 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				7539169AF2FD0C6CD1ED1213 /* libPods-FlyImageIconView.a in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		DDDEF42B1CE0AF4600C8366C /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				977F44737DA3E198C81BF6F4 /* libPods-SingleView.a in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		3F7EFE6AE8450C9D550265DA /* Pods */ = {
			isa = PBXGroup;
			children = (
				7D3083C3FEEB3316F9CCCF92 /* Pods-FlyImageIconView.debug.xcconfig */,
				02F5D49EB862BEC96204662A /* Pods-FlyImageIconView.release.xcconfig */,
				841CA4D45E6400A9646A0F66 /* Pods-FlyImageView.debug.xcconfig */,
				3ABB5A3F814E3BFC95A513BD /* Pods-FlyImageView.release.xcconfig */,
				FF39DAB46C23D364F5631D94 /* Pods-SingleView.debug.xcconfig */,
				33A4E8609F3283491E3DD133 /* Pods-SingleView.release.xcconfig */,
				D95E1058D32716446EB3DC84 /* Pods-WebP.debug.xcconfig */,
				E8620E15B0D1F42DDE6C37AA /* Pods-WebP.release.xcconfig */,
			);
			name = Pods;
			sourceTree = "<group>";
		};
		566B055403ECA67AB6D690C2 /* Frameworks */ = {
			isa = PBXGroup;
			children = (
				5F9C3948F7DFDB6E2FE5F0B0 /* libPods-FlyImageIconView.a */,
				9DCBFE3EE450E44921AFAF53 /* libPods-FlyImageView.a */,
				0280F6E421151FBFAE698C23 /* libPods-SingleView.a */,
				4EC1098E069AA6CA893D0F2C /* libPods-WebP.a */,
			);
			name = Frameworks;
			sourceTree = "<group>";
		};
		DD9D973A1CC5044D008F279E = {
			isa = PBXGroup;
			children = (
				DD9D97451CC5044D008F279E /* FlyImageView */,
				DDD1F1571CD084E500EEC549 /* FlyImageIconView */,
				DDBED1771CD8C5D600EC9263 /* WebP */,
				DDDEF42F1CE0AF4600C8366C /* SingleView */,
				DD9D97441CC5044D008F279E /* Products */,
				3F7EFE6AE8450C9D550265DA /* Pods */,
				566B055403ECA67AB6D690C2 /* Frameworks */,
			);
			sourceTree = "<group>";
		};
		DD9D97441CC5044D008F279E /* Products */ = {
			isa = PBXGroup;
			children = (
				DD9D97431CC5044D008F279E /* FlyImageView.app */,
				DDD1F1561CD084E500EEC549 /* FlyImageIconView.app */,
				DDBED1761CD8C5D600EC9263 /* WebP.app */,
				DDDEF42E1CE0AF4600C8366C /* SingleView.app */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		DD9D97451CC5044D008F279E /* FlyImageView */ = {
			isa = PBXGroup;
			children = (
				DDD1F13A1CD0832400EEC549 /* Cells */,
				DD9D97491CC5044D008F279E /* AppDelegate.h */,
				DD9D974A1CC5044D008F279E /* AppDelegate.m */,
				DDD1F1371CD0831F00EEC549 /* RootViewController.h */,
				DDD1F1381CD0831F00EEC549 /* RootViewController.m */,
				DD9D97571CC5044D008F279E /* Info.plist */,
				DD9D97461CC5044D008F279E /* Supporting Files */,
				DDD8FB5F1D59EB9200821392 /* Launch Screen.storyboard */,
			);
			path = FlyImageView;
			sourceTree = "<group>";
		};
		DD9D97461CC5044D008F279E /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				DDD1F1501CD083B300EEC549 /* Default-568h@2x.png */,
				DD9D97471CC5044D008F279E /* main.m */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
		DDBED1771CD8C5D600EC9263 /* WebP */ = {
			isa = PBXGroup;
			children = (
				DDBED17B1CD8C5D600EC9263 /* AppDelegate.h */,
				DDBED17C1CD8C5D600EC9263 /* AppDelegate.m */,
				DDBED1891CD8C5D600EC9263 /* Info.plist */,
				DDBED1781CD8C5D600EC9263 /* Supporting Files */,
			);
			path = WebP;
			sourceTree = "<group>";
		};
		DDBED1781CD8C5D600EC9263 /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				DDBED1791CD8C5D600EC9263 /* main.m */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
		DDD1F13A1CD0832400EEC549 /* Cells */ = {
			isa = PBXGroup;
			children = (
				DDD1F13B1CD0832400EEC549 /* BaseTableViewCell.h */,
				DDD1F13C1CD0832400EEC549 /* BaseTableViewCell.m */,
				DDD1F1411CD0832400EEC549 /* FlyImageLayerTableViewCell.h */,
				DDD1F1421CD0832400EEC549 /* FlyImageLayerTableViewCell.m */,
				DDD1F1431CD0832400EEC549 /* FlyImageTableViewCell.h */,
				DDD1F1441CD0832400EEC549 /* FlyImageTableViewCell.m */,
				DDD1F1451CD0832400EEC549 /* SDWebImageTableViewCell.h */,
				DDD1F1461CD0832400EEC549 /* SDWebImageTableViewCell.m */,
				DDD1F1471CD0832400EEC549 /* TriditionTableViewCell.h */,
				DDD1F1481CD0832400EEC549 /* TriditionTableViewCell.m */,
				DDD1F19E1CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.h */,
				DDD1F19F1CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.m */,
				DDBECFCB1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.h */,
				DDBECFCC1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.m */,
				DD8E088C1D5DD5BD00FEBC3A /* ProgressImageView.h */,
				DD8E088D1D5DD5BD00FEBC3A /* ProgressImageView.m */,
			);
			path = Cells;
			sourceTree = "<group>";
		};
		DDD1F1571CD084E500EEC549 /* FlyImageIconView */ = {
			isa = PBXGroup;
			children = (
				DDD1F15B1CD084E500EEC549 /* AppDelegate.h */,
				DDD1F15C1CD084E500EEC549 /* AppDelegate.m */,
				DDD1F1691CD084E500EEC549 /* Info.plist */,
				DDD1F1581CD084E500EEC549 /* Supporting Files */,
			);
			path = FlyImageIconView;
			sourceTree = "<group>";
		};
		DDD1F1581CD084E500EEC549 /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				DDD1F1591CD084E500EEC549 /* main.m */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
		DDDEF42F1CE0AF4600C8366C /* SingleView */ = {
			isa = PBXGroup;
			children = (
				DDDEF4331CE0AF4600C8366C /* AppDelegate.h */,
				DDDEF4341CE0AF4600C8366C /* AppDelegate.m */,
				DDDEF4361CE0AF4600C8366C /* SingleViewController.h */,
				DDDEF4371CE0AF4600C8366C /* SingleViewController.m */,
				DDDEF4411CE0AF4600C8366C /* Info.plist */,
				DDDEF4301CE0AF4600C8366C /* Supporting Files */,
			);
			path = SingleView;
			sourceTree = "<group>";
		};
		DDDEF4301CE0AF4600C8366C /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				DDDEF4311CE0AF4600C8366C /* main.m */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		DD9D97421CC5044D008F279E /* FlyImageView */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = DD9D97651CC5044D008F279E /* Build configuration list for PBXNativeTarget "FlyImageView" */;
			buildPhases = (
				7BB62688892610CDF5BF155B /* [CP] Check Pods Manifest.lock */,
				DD9D973F1CC5044D008F279E /* Sources */,
				DD9D97401CC5044D008F279E /* Frameworks */,
				DD9D97411CC5044D008F279E /* Resources */,
				AF73610CB4A4FC61F7066FFF /* [CP] Embed Pods Frameworks */,
				FC8AB57C3D212803BBD51308 /* [CP] Copy Pods Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = FlyImageView;
			productName = FlyImageView;
			productReference = DD9D97431CC5044D008F279E /* FlyImageView.app */;
			productType = "com.apple.product-type.application";
		};
		DDBED1751CD8C5D600EC9263 /* WebP */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = DDBED1991CD8C5D600EC9263 /* Build configuration list for PBXNativeTarget "WebP" */;
			buildPhases = (
				F81A2E353A1692446C6C00E7 /* [CP] Check Pods Manifest.lock */,
				DDBED1721CD8C5D600EC9263 /* Sources */,
				DDBED1731CD8C5D600EC9263 /* Frameworks */,
				DDBED1741CD8C5D600EC9263 /* Resources */,
				E33D266BAC01DC9109F97E25 /* [CP] Embed Pods Frameworks */,
				EC7C9F769F09EA99C51E707D /* [CP] Copy Pods Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = WebP;
			productName = WebP;
			productReference = DDBED1761CD8C5D600EC9263 /* WebP.app */;
			productType = "com.apple.product-type.application";
		};
		DDD1F1551CD084E500EEC549 /* FlyImageIconView */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = DDD1F1751CD084E500EEC549 /* Build configuration list for PBXNativeTarget "FlyImageIconView" */;
			buildPhases = (
				1DE98FA8A78C1C6538E9434F /* [CP] Check Pods Manifest.lock */,
				DDD1F1521CD084E500EEC549 /* Sources */,
				DDD1F1531CD084E500EEC549 /* Frameworks */,
				DDD1F1541CD084E500EEC549 /* Resources */,
				EC7C322CCF25D58E17ADE873 /* [CP] Embed Pods Frameworks */,
				3D1664DB16FAAE5424CC6B29 /* [CP] Copy Pods Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = FlyImageIconView;
			productName = FlyImageIconView;
			productReference = DDD1F1561CD084E500EEC549 /* FlyImageIconView.app */;
			productType = "com.apple.product-type.application";
		};
		DDDEF42D1CE0AF4600C8366C /* SingleView */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = DDDEF4441CE0AF4600C8366C /* Build configuration list for PBXNativeTarget "SingleView" */;
			buildPhases = (
				0A926CE0EFE2DD6A4B6420AC /* [CP] Check Pods Manifest.lock */,
				DDDEF42A1CE0AF4600C8366C /* Sources */,
				DDDEF42B1CE0AF4600C8366C /* Frameworks */,
				DDDEF42C1CE0AF4600C8366C /* Resources */,
				AA1CE48E20A4B22B24FDCBE0 /* [CP] Embed Pods Frameworks */,
				1FE7AD92C126F35569E2DA7F /* [CP] Copy Pods Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = SingleView;
			productName = SingleView;
			productReference = DDDEF42E1CE0AF4600C8366C /* SingleView.app */;
			productType = "com.apple.product-type.application";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		DD9D973B1CC5044D008F279E /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastUpgradeCheck = 0830;
				ORGANIZATIONNAME = Augmn;
				TargetAttributes = {
					DD9D97421CC5044D008F279E = {
						CreatedOnToolsVersion = 7.3;
					};
					DDBED1751CD8C5D600EC9263 = {
						CreatedOnToolsVersion = 7.3;
					};
					DDD1F1551CD084E500EEC549 = {
						CreatedOnToolsVersion = 7.3;
					};
					DDDEF42D1CE0AF4600C8366C = {
						CreatedOnToolsVersion = 7.3;
					};
				};
			};
			buildConfigurationList = DD9D973E1CC5044D008F279E /* Build configuration list for PBXProject "FlyImageView" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
				Base,
			);
			mainGroup = DD9D973A1CC5044D008F279E;
			productRefGroup = DD9D97441CC5044D008F279E /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				DD9D97421CC5044D008F279E /* FlyImageView */,
				DDD1F1551CD084E500EEC549 /* FlyImageIconView */,
				DDBED1751CD8C5D600EC9263 /* WebP */,
				DDDEF42D1CE0AF4600C8366C /* SingleView */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		DD9D97411CC5044D008F279E /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				DDD8FB601D59EB9200821392 /* Launch Screen.storyboard in Resources */,
				DDD1F1511CD083B300EEC549 /* Default-568h@2x.png in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		DDBED1741CD8C5D600EC9263 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				DDD8FB621D59EB9200821392 /* Launch Screen.storyboard in Resources */,
				DDBED1A11CD8C76700EC9263 /* Default-568h@2x.png in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		DDD1F1541CD084E500EEC549 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				DDD8FB611D59EB9200821392 /* Launch Screen.storyboard in Resources */,
				DDD1F1951CD08E7D00EEC549 /* Default-568h@2x.png in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		DDDEF42C1CE0AF4600C8366C /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				DDD8FB631D59EB9200821392 /* Launch Screen.storyboard in Resources */,
				DDDEF4451CE0B8AA00C8366C /* Default-568h@2x.png in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
		0A926CE0EFE2DD6A4B6420AC /* [CP] Check Pods Manifest.lock */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Check Pods Manifest.lock";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "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";
			showEnvVarsInLog = 0;
		};
		1DE98FA8A78C1C6538E9434F /* [CP] Check Pods Manifest.lock */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Check Pods Manifest.lock";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "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";
			showEnvVarsInLog = 0;
		};
		1FE7AD92C126F35569E2DA7F /* [CP] Copy Pods Resources */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Copy Pods Resources";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SingleView/Pods-SingleView-resources.sh\"\n";
			showEnvVarsInLog = 0;
		};
		3D1664DB16FAAE5424CC6B29 /* [CP] Copy Pods Resources */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Copy Pods Resources";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FlyImageIconView/Pods-FlyImageIconView-resources.sh\"\n";
			showEnvVarsInLog = 0;
		};
		7BB62688892610CDF5BF155B /* [CP] Check Pods Manifest.lock */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Check Pods Manifest.lock";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "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";
			showEnvVarsInLog = 0;
		};
		AA1CE48E20A4B22B24FDCBE0 /* [CP] Embed Pods Frameworks */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Embed Pods Frameworks";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SingleView/Pods-SingleView-frameworks.sh\"\n";
			showEnvVarsInLog = 0;
		};
		AF73610CB4A4FC61F7066FFF /* [CP] Embed Pods Frameworks */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Embed Pods Frameworks";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FlyImageView/Pods-FlyImageView-frameworks.sh\"\n";
			showEnvVarsInLog = 0;
		};
		E33D266BAC01DC9109F97E25 /* [CP] Embed Pods Frameworks */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Embed Pods Frameworks";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WebP/Pods-WebP-frameworks.sh\"\n";
			showEnvVarsInLog = 0;
		};
		EC7C322CCF25D58E17ADE873 /* [CP] Embed Pods Frameworks */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Embed Pods Frameworks";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FlyImageIconView/Pods-FlyImageIconView-frameworks.sh\"\n";
			showEnvVarsInLog = 0;
		};
		EC7C9F769F09EA99C51E707D /* [CP] Copy Pods Resources */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Copy Pods Resources";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-WebP/Pods-WebP-resources.sh\"\n";
			showEnvVarsInLog = 0;
		};
		F81A2E353A1692446C6C00E7 /* [CP] Check Pods Manifest.lock */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Check Pods Manifest.lock";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "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";
			showEnvVarsInLog = 0;
		};
		FC8AB57C3D212803BBD51308 /* [CP] Copy Pods Resources */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Copy Pods Resources";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FlyImageView/Pods-FlyImageView-resources.sh\"\n";
			showEnvVarsInLog = 0;
		};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		DD9D973F1CC5044D008F279E /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				DDD1F1491CD0832400EEC549 /* BaseTableViewCell.m in Sources */,
				DD8E088E1D5DD5BD00FEBC3A /* ProgressImageView.m in Sources */,
				DDD1F14E1CD0832400EEC549 /* SDWebImageTableViewCell.m in Sources */,
				DD9D974B1CC5044D008F279E /* AppDelegate.m in Sources */,
				DDD1F14F1CD0832400EEC549 /* TriditionTableViewCell.m in Sources */,
				DDD1F14D1CD0832400EEC549 /* FlyImageTableViewCell.m in Sources */,
				DDD1F14C1CD0832400EEC549 /* FlyImageLayerTableViewCell.m in Sources */,
				DD9D97481CC5044D008F279E /* main.m in Sources */,
				DDD1F1391CD0831F00EEC549 /* RootViewController.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		DDBED1721CD8C5D600EC9263 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				DD2EDB131D61E6C30085C9E3 /* ProgressImageView.m in Sources */,
				DDBED17D1CD8C5D600EC9263 /* AppDelegate.m in Sources */,
				DDBED19B1CD8C70C00EC9263 /* RootViewController.m in Sources */,
				DDBED19D1CD8C71900EC9263 /* TriditionTableViewCell.m in Sources */,
				DDBED19F1CD8C72A00EC9263 /* FlyImageTableViewCell.m in Sources */,
				DDBED19E1CD8C71B00EC9263 /* SDWebImageTableViewCell.m in Sources */,
				DDBED19C1CD8C71100EC9263 /* BaseTableViewCell.m in Sources */,
				DDBED1A01CD8C72E00EC9263 /* FlyImageLayerTableViewCell.m in Sources */,
				DDBED17A1CD8C5D600EC9263 /* main.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		DDD1F1521CD084E500EEC549 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				DDD1F1941CD08D1E00EEC549 /* RootViewController.m in Sources */,
				DDD1F18F1CD0872D00EEC549 /* BaseTableViewCell.m in Sources */,
				DDD1F1A01CD0B92F00EEC549 /* FlyImageIconLayerTableViewCell.m in Sources */,
				DDD1F1911CD0872D00EEC549 /* SDWebImageTableViewCell.m in Sources */,
				DDD1F1931CD0872D00EEC549 /* TriditionTableViewCell.m in Sources */,
				DDD1F15D1CD084E500EEC549 /* AppDelegate.m in Sources */,
				DDD1F15A1CD084E500EEC549 /* main.m in Sources */,
				DDBECFCD1CD8C0FA00EC9263 /* FlyImageIconViewTableViewCell.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		DDDEF42A1CE0AF4600C8366C /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				DDDEF4381CE0AF4600C8366C /* SingleViewController.m in Sources */,
				DDDEF4351CE0AF4600C8366C /* AppDelegate.m in Sources */,
				DDDEF4321CE0AF4600C8366C /* main.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin XCBuildConfiguration section */
		DD9D97631CC5044D008F279E /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = dwarf;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				MTL_ENABLE_DEBUG_INFO = YES;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
				TARGETED_DEVICE_FAMILY = "1,2";
			};
			name = Debug;
		};
		DD9D97641CC5044D008F279E /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				MTL_ENABLE_DEBUG_INFO = NO;
				SDKROOT = iphoneos;
				TARGETED_DEVICE_FAMILY = "1,2";
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		DD9D97661CC5044D008F279E /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 841CA4D45E6400A9646A0F66 /* Pods-FlyImageView.debug.xcconfig */;
			buildSettings = {
				CODE_SIGN_IDENTITY = "iPhone Developer";
				INFOPLIST_FILE = FlyImageView/Info.plist;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.augmn.test;
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Debug;
		};
		DD9D97671CC5044D008F279E /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 3ABB5A3F814E3BFC95A513BD /* Pods-FlyImageView.release.xcconfig */;
			buildSettings = {
				CODE_SIGN_IDENTITY = "iPhone Developer";
				INFOPLIST_FILE = FlyImageView/Info.plist;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.augmn.test;
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Release;
		};
		DDBED1951CD8C5D600EC9263 /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = D95E1058D32716446EB3DC84 /* Pods-WebP.debug.xcconfig */;
			buildSettings = {
				INFOPLIST_FILE = WebP/Info.plist;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageview.WebP;
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Debug;
		};
		DDBED1961CD8C5D600EC9263 /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = E8620E15B0D1F42DDE6C37AA /* Pods-WebP.release.xcconfig */;
			buildSettings = {
				INFOPLIST_FILE = WebP/Info.plist;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageview.WebP;
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Release;
		};
		DDD1F1761CD084E500EEC549 /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 7D3083C3FEEB3316F9CCCF92 /* Pods-FlyImageIconView.debug.xcconfig */;
			buildSettings = {
				INFOPLIST_FILE = FlyImageIconView/Info.plist;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageiconview;
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Debug;
		};
		DDD1F1771CD084E500EEC549 /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 02F5D49EB862BEC96204662A /* Pods-FlyImageIconView.release.xcconfig */;
			buildSettings = {
				INFOPLIST_FILE = FlyImageIconView/Info.plist;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageiconview;
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Release;
		};
		DDDEF4421CE0AF4600C8366C /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = FF39DAB46C23D364F5631D94 /* Pods-SingleView.debug.xcconfig */;
			buildSettings = {
				INFOPLIST_FILE = SingleView/Info.plist;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageview.SingleView;
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Debug;
		};
		DDDEF4431CE0AF4600C8366C /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 33A4E8609F3283491E3DD133 /* Pods-SingleView.release.xcconfig */;
			buildSettings = {
				INFOPLIST_FILE = SingleView/Info.plist;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
				PRODUCT_BUNDLE_IDENTIFIER = com.augmn.flyimageview.SingleView;
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		DD9D973E1CC5044D008F279E /* Build configuration list for PBXProject "FlyImageView" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				DD9D97631CC5044D008F279E /* Debug */,
				DD9D97641CC5044D008F279E /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		DD9D97651CC5044D008F279E /* Build configuration list for PBXNativeTarget "FlyImageView" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				DD9D97661CC5044D008F279E /* Debug */,
				DD9D97671CC5044D008F279E /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		DDBED1991CD8C5D600EC9263 /* Build configuration list for PBXNativeTarget "WebP" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				DDBED1951CD8C5D600EC9263 /* Debug */,
				DDBED1961CD8C5D600EC9263 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		DDD1F1751CD084E500EEC549 /* Build configuration list for PBXNativeTarget "FlyImageIconView" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				DDD1F1761CD084E500EEC549 /* Debug */,
				DDD1F1771CD084E500EEC549 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		DDDEF4441CE0AF4600C8366C /* Build configuration list for PBXNativeTarget "SingleView" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				DDDEF4421CE0AF4600C8366C /* Debug */,
				DDDEF4431CE0AF4600C8366C /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = DD9D973B1CC5044D008F279E /* Project object */;
}


================================================
FILE: Examples/FlyImageView.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "group:FlyImageView.xcodeproj">
   </FileRef>
   <FileRef
      location = "group:Pods/Pods.xcodeproj">
   </FileRef>
</Workspace>


================================================
FILE: Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/FlyImageIconView.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "0830"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "DDD1F1551CD084E500EEC549"
               BuildableName = "FlyImageIconView.app"
               BlueprintName = "FlyImageIconView"
               ReferencedContainer = "container:FlyImageView.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <Testables>
      </Testables>
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DDD1F1551CD084E500EEC549"
            BuildableName = "FlyImageIconView.app"
            BlueprintName = "FlyImageIconView"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <AdditionalOptions>
      </AdditionalOptions>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DDD1F1551CD084E500EEC549"
            BuildableName = "FlyImageIconView.app"
            BlueprintName = "FlyImageIconView"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
      <AdditionalOptions>
      </AdditionalOptions>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Release"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DDD1F1551CD084E500EEC549"
            BuildableName = "FlyImageIconView.app"
            BlueprintName = "FlyImageIconView"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/FlyImageView.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "0830"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "DD9D97421CC5044D008F279E"
               BuildableName = "FlyImageView.app"
               BlueprintName = "FlyImageView"
               ReferencedContainer = "container:FlyImageView.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <Testables>
      </Testables>
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DD9D97421CC5044D008F279E"
            BuildableName = "FlyImageView.app"
            BlueprintName = "FlyImageView"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <AdditionalOptions>
      </AdditionalOptions>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DD9D97421CC5044D008F279E"
            BuildableName = "FlyImageView.app"
            BlueprintName = "FlyImageView"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
      <AdditionalOptions>
      </AdditionalOptions>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Release"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DD9D97421CC5044D008F279E"
            BuildableName = "FlyImageView.app"
            BlueprintName = "FlyImageView"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/SingleView.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "0830"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "DDDEF42D1CE0AF4600C8366C"
               BuildableName = "SingleView.app"
               BlueprintName = "SingleView"
               ReferencedContainer = "container:FlyImageView.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <Testables>
      </Testables>
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DDDEF42D1CE0AF4600C8366C"
            BuildableName = "SingleView.app"
            BlueprintName = "SingleView"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <AdditionalOptions>
      </AdditionalOptions>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DDDEF42D1CE0AF4600C8366C"
            BuildableName = "SingleView.app"
            BlueprintName = "SingleView"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
      <AdditionalOptions>
      </AdditionalOptions>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Release"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DDDEF42D1CE0AF4600C8366C"
            BuildableName = "SingleView.app"
            BlueprintName = "SingleView"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/WebP.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "0830"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "DDBED1751CD8C5D600EC9263"
               BuildableName = "WebP.app"
               BlueprintName = "WebP"
               ReferencedContainer = "container:FlyImageView.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES">
      <Testables>
      </Testables>
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DDBED1751CD8C5D600EC9263"
            BuildableName = "WebP.app"
            BlueprintName = "WebP"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <AdditionalOptions>
      </AdditionalOptions>
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DDBED1751CD8C5D600EC9263"
            BuildableName = "WebP.app"
            BlueprintName = "WebP"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
      <AdditionalOptions>
      </AdditionalOptions>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Release"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "DDBED1751CD8C5D600EC9263"
            BuildableName = "WebP.app"
            BlueprintName = "WebP"
            ReferencedContainer = "container:FlyImageView.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: Examples/Podfile
================================================
platform :ios, '8.0'

# ignore all warnings from all pods
inhibit_all_warnings!

target 'FlyImageView' do
	pod 'SDWebImage', '~> 3.7'
	pod 'FlyImage', :path => '../FlyImage.podspec'
end

target 'FlyImageIconView' do
	pod 'SDWebImage', '~> 3.7'
	pod 'FlyImage', :path => '../FlyImage.podspec'
end

target 'WebP' do
	pod 'SDWebImage/WebP', '~> 3.7'
	pod 'FlyImage/WebP', :path => '../FlyImage.podspec'
end

target 'SingleView' do
	pod 'FlyImage', :path => '../FlyImage.podspec'
end


================================================
FILE: Examples/SingleView/AppDelegate.h
================================================
//
//  AppDelegate.h
//  SingleView
//
//  Created by Ye Tong on 5/9/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;


@end



================================================
FILE: Examples/SingleView/AppDelegate.m
================================================
//
//  AppDelegate.m
//  SingleView
//
//  Created by Ye Tong on 5/9/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import "AppDelegate.h"
#import "SingleViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
	// Override point for customization after application launch.
	self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
	self.window.backgroundColor = [UIColor blackColor];
	
	SingleViewController *rootViewController = [[SingleViewController alloc] init];
	self.window.rootViewController = rootViewController;
	[self.window makeKeyAndVisible];
	
	return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
	// 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.
	// 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.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
	// 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.
	// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
	// 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.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
	// 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.
}

- (void)applicationWillTerminate:(UIApplication *)application {
	// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end


================================================
FILE: Examples/SingleView/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
	</dict>
	<key>UILaunchStoryboardName</key>
	<string>Launch Screen</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UIRequiresFullScreen</key>
	<true/>
	<key>UIStatusBarHidden</key>
	<false/>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
FILE: Examples/SingleView/SingleViewController.h
================================================
//
//  ViewController.h
//  SingleView
//
//  Created by Ye Tong on 5/9/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface SingleViewController : UIViewController


@end



================================================
FILE: Examples/SingleView/SingleViewController.m
================================================
//
//  SingleViewController.m
//  SingleView
//
//  Created by Ye Tong on 5/9/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import "SingleViewController.h"
#import "FlyImage.h"

@implementation SingleViewController {
	NSMutableArray *_imageViews;
	NSMutableArray *_iconViews;
}

- (BOOL)prefersStatusBarHidden {
	return YES;
}

- (void)viewDidLoad {
	[super viewDidLoad];
	[FlyImageCache sharedInstance].autoDismissImage = YES;
	
	_imageViews = [NSMutableArray new];
	_iconViews = [NSMutableArray new];
	
	// add // remove // clear
	CGFloat fromY = self.view.bounds.size.height - 200;
	[self insertButtonWithTitle:@"AddImageView" selector:@selector(onAddImageView) point:CGPointMake(10, fromY)];
	[self insertButtonWithTitle:@"RemoveImageView" selector:@selector(onRemoveImageView) point:CGPointMake(self.view.bounds.size.width/2 - 40, fromY)];
	[self insertButtonWithTitle:@"ClearImageViews" selector:@selector(onClearImageViews) point:CGPointMake(self.view.bounds.size.width - 90, fromY)];
	
	[self insertButtonWithTitle:@"AddIconView" selector:@selector(onAddIconView) point:CGPointMake(10, fromY + 100)];
	[self insertButtonWithTitle:@"RemoveIconView" selector:@selector(onRemoveIconView) point:CGPointMake(self.view.bounds.size.width/2 - 40, fromY + 100)];
	[self insertButtonWithTitle:@"ClearIconViews" selector:@selector(onClearIconViews) point:CGPointMake(self.view.bounds.size.width - 90, fromY + 100)];
	
}

- (void)insertButtonWithTitle:(NSString *)title selector:(SEL)selector point:(CGPoint)point {
	UIButton *addButton = [UIButton buttonWithType:UIButtonTypeSystem];
	addButton.frame = CGRectMake(point.x, point.y, 80, 44);
	addButton.backgroundColor = [UIColor orangeColor];
	[addButton setTitle:title forState:UIControlStateNormal];
	[addButton addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside];
	addButton.titleLabel.adjustsFontSizeToFitWidth = YES;
	[self.view addSubview:addButton];
}

- (void)onAddImageView {
	static NSInteger kCount = 0;
	
	NSMutableArray *imagesInRow = [NSMutableArray new];
	CGFloat size = self.view.bounds.size.width / 5;
	NSInteger index = kCount % 100;
	
	for (NSInteger i=0; i<4; i++) {
		UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(i * (size + 10), [_imageViews count] * (size + 10), size, size)];
		NSURL *url = [NSURL URLWithString: [NSString stringWithFormat:@"http://liuliantv.oss-cn-beijing.aliyuncs.com/flyimage/%ld.jpg", (long)index]];
		imageView.imageURL = url;
		[self.view insertSubview:imageView atIndex:0];
		
		[imagesInRow addObject:imageView];
	}
	
	[_imageViews addObject:imagesInRow];
	kCount++;
}

- (void)onRemoveImageView {
	NSArray *imagesInRow = [_imageViews lastObject];
	for (UIImageView *imageView in imagesInRow) {
		[imageView removeFromSuperview];
	}
	
	[_imageViews removeLastObject];
}

- (void)onClearImageViews {
	for (NSArray *imagesInRow in _imageViews) {
		for (UIImageView *imageView in imagesInRow) {
			[imageView removeFromSuperview];
		}
	}
	
	[_imageViews removeAllObjects];
}

- (void)onAddIconView {
	static NSInteger kCount = 0;
	
	NSMutableArray *imagesInRow = [NSMutableArray new];
	CGFloat size = self.view.bounds.size.width / 5;
	NSInteger index = kCount % 100;
	
	for (NSInteger i=0; i<4; i++) {
		UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(i * (size + 10), [_iconViews count] * (size + 10), size, size)];
		NSURL *url = [NSURL URLWithString: [NSString stringWithFormat:@"http://liuliantv.oss-cn-beijing.aliyuncs.com/flyimage/%ld_tn.jpg", (long)index]];
		imageView.iconURL = url;
		[self.view insertSubview:imageView atIndex:0];
		
		[imagesInRow addObject:imageView];
	}
	
	[_iconViews addObject:imagesInRow];
	kCount++;
}

- (void)onRemoveIconView {
	NSArray *imagesInRow = [_iconViews lastObject];
	for (UIImageView *imageView in imagesInRow) {
		[imageView removeFromSuperview];
	}
	
	[_iconViews removeLastObject];
}

- (void)onClearIconViews {
	for (NSArray *imagesInRow in _iconViews) {
		for (UIImageView *imageView in imagesInRow) {
			[imageView removeFromSuperview];
		}
	}
	
	[_iconViews removeAllObjects];
}

@end


================================================
FILE: Examples/SingleView/main.m
================================================
//
//  main.m
//  SingleView
//
//  Created by Ye Tong on 5/9/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
	@autoreleasepool {
	    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
	}
}


================================================
FILE: Examples/WebP/AppDelegate.h
================================================
//
//  AppDelegate.h
//  WebP
//
//  Created by Ye Tong on 5/3/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;


@end



================================================
FILE: Examples/WebP/AppDelegate.m
================================================
//
//  AppDelegate.m
//  WebP
//
//  Created by Ye Tong on 5/3/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import "AppDelegate.h"
#import "RootViewController.h"
#import "FlyImageTableViewCell.h"
#import "FlyImageLayerTableViewCell.h"
#import "SDWebImageTableViewCell.h"
#import "FlyImage.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

	self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
	self.window.backgroundColor = [UIColor whiteColor];
	
	[FlyImageCache sharedInstance].autoDismissImage = YES;
	
	RootViewController *rootViewController = [[RootViewController alloc] init];
	rootViewController.suffix = @".webp";
	rootViewController.heightOfCell = 150;
	rootViewController.cellsPerRow = 1;
	rootViewController.cells = @[ @{
									  @"class": [SDWebImageTableViewCell class],
									  @"title": @"SDWebImage"
									  } ,@{
									  @"class": [FlyImageTableViewCell class],
									  @"title": @"FlyImageView"
									  } ,@{
									  @"class": [FlyImageLayerTableViewCell class],
									  @"title": @"FlyImageLayer"
									  }];
	
	self.window.rootViewController = rootViewController;
	[self.window makeKeyAndVisible];
	
	return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
	// 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.
	// 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.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
	// 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.
	// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
	// 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.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
	// 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.
}

- (void)applicationWillTerminate:(UIApplication *)application {
	// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end


================================================
FILE: Examples/WebP/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
	</dict>
	<key>UILaunchStoryboardName</key>
	<string>Launch Screen</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UIRequiresFullScreen</key>
	<true/>
	<key>UIStatusBarHidden</key>
	<false/>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
FILE: Examples/WebP/main.m
================================================
//
//  main.m
//  WebP
//
//  Created by Ye Tong on 5/3/16.
//  Copyright © 2016 Augmn. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
	@autoreleasepool {
	    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
	}
}


================================================
FILE: FlyImage/Core/FlyImageCache.h
================================================
//
//  FlyImageCache.h
//  Demo
//
//  Created by Ye Tong on 3/17/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "FlyImageCacheProtocol.h"
@class FlyImageDataFileManager;

/**
 *	Manage image files in one folder.
 */
@interface FlyImageCache : NSObject <FlyImageCacheProtocol>

@property (nonatomic, assign) CGFloat maxCachedBytes; // Default is 512Mb.
@property (nonatomic, assign) BOOL autoDismissImage; // If you want to reduce memory when the app enter background, set this flag as YES. Default is NO.
@property (nonatomic, strong) FlyImageDataFileManager* dataFileManager;

#ifdef FLYIMAGE_WEBP
@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.
@property (nonatomic, assign) CGFloat compressionQualityForWebP; // Default is 0.8.
#endif

- (void)addImageWithKey:(NSString*)key
               filename:(NSString*)filename
              completed:(FlyImageCacheRetrieveBlock)completed;

- (void)addImageWithKey:(NSString*)key
               filename:(NSString*)filename
               drawSize:(CGSize)drawSize
        contentsGravity:(NSString* const)contentsGravity
           cornerRadius:(CGFloat)cornerRadius
              completed:(FlyImageCacheRetrieveBlock)completed;

/**
 *  Get image with customize parameters from cache asynchronously.
 *  Avoid executing `CGDataProviderCreateWithCopyOfData`.
 *
 *  @param key             image key
 *  @param drawSize        render size
 *  @param contentsGravity contentMode of render view
 *  @param cornerRadius    cornerRadius of render view
 *  @param completed       callback
 */
- (void)asyncGetImageWithKey:(NSString*)key
                    drawSize:(CGSize)drawSize
             contentsGravity:(NSString* const)contentsGravity
                cornerRadius:(CGFloat)cornerRadius
                   completed:(FlyImageCacheRetrieveBlock)completed;

/**
 *  Get the image path saved in the disk.
 */
- (NSString*)imagePathWithKey:(NSString*)key;

/**
 *  Protect the file, which can't be removed.
 *
 *  @param key image key
 */
- (void)protectFileWithKey:(NSString*)key;

/**
 *  Don't protect the file, which can be removed.
 *
 *  @param key image key
 */
- (void)unProtectFileWithKey:(NSString*)key;

@end


================================================
FILE: FlyImage/Core/FlyImageCache.m
================================================
//
//  FlyImageCache.m
//  Demo
//
//  Created by Ye Tong on 3/17/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "FlyImageCache.h"
#import "FlyImageDataFileManager.h"
#import "FlyImageUtils.h"
#import "FlyImageDecoder.h"
#import "FlyImageRetrieveOperation.h"

#define kImageInfoIndexFileName 0
#define kImageInfoIndexContentType 1
#define kImageInfoIndexWidth 2
#define kImageInfoIndexHeight 3
#define kImageInfoIndexLock 4

@interface FlyImageCache ()
@property (nonatomic, strong) FlyImageDecoder* decoder;
@end

@implementation FlyImageCache {
    NSRecursiveLock* _lock;
    NSString* _metaPath;
    NSMutableDictionary* _images;
    NSMutableDictionary* _addingImages;
    NSOperationQueue* _retrievingQueue;
}

+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    static FlyImageCache* __instance = nil;
    dispatch_once(&onceToken, ^{
		NSString *metaPath = [[FlyImageUtils directoryPath] stringByAppendingPathComponent:@"/__images"];
		__instance = [[[self class] alloc] initWithMetaPath:metaPath];
    });

    return __instance;
}

- (instancetype)initWithMetaPath:(NSString*)metaPath
{
    if (self = [self init]) {
        _lock = [[NSRecursiveLock alloc] init];
        _addingImages = [[NSMutableDictionary alloc] init];
        _maxCachedBytes = 1024 * 1024 * 512;
        _retrievingQueue = [NSOperationQueue new];
        _retrievingQueue.qualityOfService = NSQualityOfServiceUserInteractive;
        _retrievingQueue.maxConcurrentOperationCount = 6;

#ifdef FLYIMAGE_WEBP
        _autoConvertWebP = NO;
        _compressionQualityForWebP = 0.8;
#endif

        _metaPath = [metaPath copy];
        NSString* folderPath = [[_metaPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"/files"];
        self.dataFileManager = [[FlyImageDataFileManager alloc] initWithFolderPath:folderPath];

        _metaPath = [metaPath copy];
        [self loadMetadata];

        _decoder = [[FlyImageDecoder alloc] init];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(onWillTerminate)
                                                     name:UIApplicationWillTerminateNotification
                                                   object:nil];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(onDidEnterBackground)
                                                     name:UIApplicationDidEnterBackgroundNotification
                                                   object:nil];
    }
    return self;
}

#pragma mark - LifeCircle

- (void)dealloc
{
    [_retrievingQueue cancelAllOperations];

    [self cleanCachedImages];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)onWillTerminate
{
    [self cleanCachedImages];
}

- (void)onDidEnterBackground
{
    [self cleanCachedImages];
}

- (void)cleanCachedImages
{
    [_retrievingQueue cancelAllOperations];

    __weak __typeof__(self) weakSelf = self;
    [self.dataFileManager calculateSizeWithCompletionBlock:^(NSUInteger fileCount, NSUInteger totalSize) {
		if ( weakSelf.maxCachedBytes > totalSize ) {
			return;
		}
		
		NSMutableArray *lockedFilenames = [NSMutableArray array];
		NSMutableArray *lockedKeys = [NSMutableArray array];
		@synchronized (_images) {
			for (NSString *key in _images) {
				NSArray *imageInfo = [_images objectForKey:key];
				if ( [imageInfo count] > kImageInfoIndexLock && [[imageInfo objectAtIndex:kImageInfoIndexLock] boolValue] ){
					[lockedFilenames addObject:[imageInfo objectAtIndex:kImageInfoIndexFileName]];
					[lockedKeys addObject:key];
				}
			}
		}
		
		[weakSelf.dataFileManager purgeWithExceptions:lockedFilenames
															   toSize:weakSelf.maxCachedBytes/2
															completed:^(NSUInteger fileCount, NSUInteger totalSize) {
																
																// remove unlock keys
																@synchronized (_images) {
																	NSArray *allKeys = [_images allKeys];
																	for (NSString *key in allKeys) {
																		if ( [lockedKeys indexOfObject:key] == NSNotFound ) {
																			[_images removeObjectForKey:key];
																		}
																	}
																}
																
																[weakSelf saveMetadata];
															}];
    }];
}

#pragma mark - APIs
- (void)addImageWithKey:(NSString*)key
               filename:(NSString*)filename
              completed:(FlyImageCacheRetrieveBlock)completed
{
    [self addImageWithKey:key filename:filename drawSize:CGSizeZero contentsGravity:kCAGravityResizeAspect cornerRadius:0 completed:completed];
}

- (void)addImageWithKey:(NSString*)key
               filename:(NSString*)filename
               drawSize:(CGSize)drawSize
        contentsGravity:(NSString* const)contentsGravity
           cornerRadius:(CGFloat)cornerRadius
              completed:(FlyImageCacheRetrieveBlock)completed
{

    NSParameterAssert(key != nil);
    NSParameterAssert(filename != nil);

    if ([self isImageExistWithKey:key] && completed != nil) {
        [self asyncGetImageWithKey:key
                          drawSize:drawSize
                   contentsGravity:contentsGravity
                      cornerRadius:cornerRadius
                         completed:completed];
        return;
    }

    // ignore draw size when add images
    @synchronized(_addingImages)
    {
        if ([_addingImages objectForKey:key] == nil) {
            NSMutableArray* blocks = [NSMutableArray array];
            if (completed != nil) {
                [blocks addObject:completed];
            }

            [_addingImages setObject:blocks forKey:key];
        } else {
            // waiting for drawing
            NSMutableArray* blocks = [_addingImages objectForKey:key];
            if (completed != nil) {
                [blocks addObject:completed];
            }

            return;
        }
    }

    [self doAddImageWithKey:[key copy]
                   filename:[filename copy]
                   drawSize:drawSize
            contentsGravity:contentsGravity
               cornerRadius:cornerRadius
                  completed:completed];
}

- (void)doAddImageWithKey:(NSString*)key
                 filename:(NSString*)filename
                 drawSize:(CGSize)drawSize
          contentsGravity:(NSString* const)contentsGravity
             cornerRadius:(CGFloat)cornerRadius
                completed:(FlyImageCacheRetrieveBlock)completed
{

    static dispatch_queue_t __drawingQueue = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
		NSString *name = [NSString stringWithFormat:@"com.flyimage.addimage.%@", [[NSUUID UUID] UUIDString]];
		__drawingQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], NULL);
    });

    dispatch_async(__drawingQueue, ^{
		
		// get image meta
		CGSize imageSize = CGSizeZero;
		ImageContentType contentType;
		@autoreleasepool {
			NSString *filePath = [self.dataFileManager.folderPath stringByAppendingPathComponent:filename];
			NSData *fileData = [NSData dataWithContentsOfFile:filePath];
			contentType = [FlyImageUtils contentTypeForImageData:fileData];
			UIImage *image = nil;
			if ( contentType == ImageContentTypeWebP ) {
#ifdef FLYIMAGE_WEBP
				if ( _autoConvertWebP ) {
					// Decode WebP
					BOOL hasAlpha;
					image = [_decoder imageWithWebPData:fileData hasAlpha:&hasAlpha];
					if ( image != nil ) {
						NSData *compresstionImageData;
						if ( hasAlpha ) {
							// Convert WebP to PNG
							compresstionImageData = UIImagePNGRepresentation(image);
							if ( compresstionImageData != nil ){
								contentType = ImageContentTypePNG;
							}
						}else{
							// Convert WebP to JPEG
							compresstionImageData = UIImageJPEGRepresentation(image, self.compressionQualityForWebP);
							if ( compresstionImageData != nil ){
								contentType = ImageContentTypeJPEG;
							}
						}

						// save image into disk
						if ( compresstionImageData != nil ){
							NSString *filePath = [self.dataFileManager.folderPath stringByAppendingPathComponent:filename];
							[compresstionImageData writeToFile:filePath atomically:YES];
						}
					}
				}
#endif
			}else{
				// read image meta, not data
				image = [UIImage imageWithData:fileData];
			}
			
			imageSize = image.size;
		}
		
		[self.dataFileManager addExistFileName:filename];
		FlyImageDataFile *dataFile = [self.dataFileManager retrieveFileWithName:filename];
		if ( [dataFile open] == false ) {
			[self afterAddImage:nil key:key];
			return;
		}
		
		// save data file's param
		void *bytes = dataFile.address;
		size_t fileLength = (size_t)dataFile.fileLength;
		
		// callback with image
		UIImage *decodeImage = [_decoder imageWithFile:(__bridge void *)(dataFile)
                                             contentType:contentType
                                                   bytes:bytes
                                                  length:fileLength
                                                drawSize:CGSizeEqualToSize(drawSize, CGSizeZero) ? imageSize : drawSize
                                         contentsGravity:contentsGravity
                                            cornerRadius:cornerRadius];
		[self afterAddImage:decodeImage key:key];
		
		@synchronized (_images) {
			// path, width, height, length
			NSArray *imageInfo = @[ filename,
									@(contentType),
									@(imageSize.width),
									@(imageSize.height) ];
			
			[_images setObject:imageInfo forKey:key];
		}
		
		// save meta
		[self saveMetadata];
    });
}

- (void)afterAddImage:(UIImage*)image key:(NSString*)key
{
    NSArray* blocks = nil;
    @synchronized(_addingImages)
    {
        blocks = [[_addingImages objectForKey:key] copy];
        [_addingImages removeObjectForKey:key];
    }

    dispatch_main_sync_safe(^{
        for ( FlyImageCacheRetrieveBlock block in blocks) {
            block( key, image );
        }
    });
}

- (void)removeImageWithKey:(NSString*)key
{
    NSString* fileName = nil;
    @synchronized(_images)
    {

        NSArray* imageInfo = [_images objectForKey:key];
        if (imageInfo == nil) {
            return;
        }

        // if locked
        if ([imageInfo count] > kImageInfoIndexLock && [[imageInfo objectAtIndex:kImageInfoIndexLock] boolValue] == YES) {
            return;
        }

        [_images removeObjectForKey:key];

        fileName = [imageInfo firstObject];
    }

    if (fileName != nil) {
        [self.dataFileManager removeFileWithName:fileName];
    }
}

- (void)changeImageKey:(NSString*)oldKey newKey:(NSString*)newKey
{
    @synchronized(_images)
    {
        id imageInfo = [_images objectForKey:oldKey];
        if (imageInfo == nil) {
            return;
        }

        [_images setObject:imageInfo forKey:newKey];
        [_images removeObjectForKey:oldKey];
    }
}

- (BOOL)isImageExistWithKey:(NSString*)key
{
    NSParameterAssert(key != nil);

    @synchronized(_images)
    {
        return [_images objectForKey:key] != nil;
    }
}

- (void)asyncGetImageWithKey:(NSString*)key completed:(FlyImageCacheRetrieveBlock)completed
{
    [self asyncGetImageWithKey:key drawSize:CGSizeZero contentsGravity:kCAGravityResizeAspect cornerRadius:0 completed:completed];
}

- (void)asyncGetImageWithKey:(NSString*)key
                    drawSize:(CGSize)drawSize
             contentsGravity:(NSString* const)contentsGravity
                cornerRadius:(CGFloat)cornerRadius
                   completed:(FlyImageCacheRetrieveBlock)completed
{
    NSParameterAssert(key != nil);
    NSParameterAssert(completed != nil);

    NSArray* imageInfo;
    @synchronized(_images)
    {
        imageInfo = [_images objectForKey:key];
    }

    if (imageInfo == nil || [imageInfo count] <= kImageInfoIndexHeight) {
        completed(key, nil);
        return;
    }

    // filename, width, height, length
    NSString* filename = [imageInfo firstObject];
    FlyImageDataFile* dataFile = [self.dataFileManager retrieveFileWithName:filename];
    if (dataFile == nil) {
        completed(key, nil);
        return;
    }

    // if the image is retrieving, then just add the block, no need to create a new operation.
    for (FlyImageRetrieveOperation* operation in _retrievingQueue.operations) {
        if ([operation.name isEqualToString:key]) {
            [operation addBlock:completed];
            return;
        }
    }

    CGSize imageSize = drawSize;
    if (drawSize.width == 0 && drawSize.height == 0) {
        CGFloat imageWidth = [[imageInfo objectAtIndex:kImageInfoIndexWidth] floatValue];
        CGFloat imageHeight = [[imageInfo objectAtIndex:kImageInfoIndexHeight] floatValue];
        imageSize = CGSizeMake(imageWidth, imageHeight);
    }
    ImageContentType contentType = [[imageInfo objectAtIndex:kImageInfoIndexContentType] integerValue];

    __weak __typeof__(self) weakSelf = self;
    FlyImageRetrieveOperation* operation = [[FlyImageRetrieveOperation alloc] initWithRetrieveBlock:^UIImage * {
																						 if ( ![dataFile open] ) {
																							 return nil;
																						 }
																						 
																						 return [weakSelf.decoder imageWithFile:(__bridge void *)(dataFile)
																													  contentType:contentType
																															bytes:dataFile.address
																														   length:(size_t)dataFile.fileLength
																														 drawSize:CGSizeEqualToSize(drawSize, CGSizeZero) ? imageSize : drawSize
																												  contentsGravity:contentsGravity
																													 cornerRadius:cornerRadius];
    }];
    operation.name = key;
    [operation addBlock:completed];
    [_retrievingQueue addOperation:operation];
}

- (void)cancelGetImageWithKey:(NSString*)key
{
    NSParameterAssert(key != nil);

    for (FlyImageRetrieveOperation* operation in _retrievingQueue.operations) {
        if (!operation.cancelled && !operation.finished && [operation.name isEqualToString:key]) {
            [operation cancel];
            return;
        }
    }
}

- (void)purge
{

    NSMutableArray* lockedFilenames = [NSMutableArray array];
    @synchronized(_images)
    {
        NSMutableArray* lockedKeys = [NSMutableArray array];
        for (NSString* key in _images) {
            NSArray* imageInfo = [_images objectForKey:key];
            if ([imageInfo count] > kImageInfoIndexLock && [[imageInfo objectAtIndex:kImageInfoIndexLock] boolValue]) {
                [lockedFilenames addObject:[imageInfo objectAtIndex:kImageInfoIndexFileName]];
                [lockedKeys addObject:key];
            }
        }

        // remove unlock keys
        NSArray* allKeys = [_images allKeys];
        for (NSString* key in allKeys) {
            if ([lockedKeys indexOfObject:key] == NSNotFound) {
                [_images removeObjectForKey:key];
            }
        }
    }

    [_retrievingQueue cancelAllOperations];

    @synchronized(_addingImages)
    {
        for (NSString* key in _addingImages) {
            NSArray* blocks = [_addingImages objectForKey:key];
            dispatch_main_sync_safe(^{
                for ( FlyImageCacheRetrieveBlock block in blocks) {
                    block( key, nil );
                }
            });
        }

        [_addingImages removeAllObjects];
    }

    // remove files
    [self.dataFileManager purgeWithExceptions:lockedFilenames toSize:0 completed:nil];

    [self saveMetadata];
}

- (NSString*)imagePathWithKey:(NSString*)key
{
    NSParameterAssert(key != nil);

    @synchronized(_images)
    {
        NSArray* fileInfo = [_images objectForKey:key];
        if ([fileInfo firstObject] == nil) {
            return nil;
        }

        NSString* filename = [fileInfo objectAtIndex:kImageInfoIndexFileName];
        return [self.dataFileManager.folderPath stringByAppendingPathComponent:filename];
    }
}

// 锁住文件,不能被回收
- (void)protectFileWithKey:(NSString*)key
{
    NSParameterAssert(key != nil);

    if (![self isImageExistWithKey:key]) {
        return;
    }

    @synchronized(_images)
    {
        NSArray* fileInfo = [_images objectForKey:key];
        if ([fileInfo firstObject] == nil) {
            return;
        }

        // alread locked
        if ([fileInfo count] > kImageInfoIndexLock && [[fileInfo objectAtIndex:kImageInfoIndexLock] boolValue]) {
            return;
        }

        // name, type, width, height, lock
        NSMutableArray* newFileInfo = [NSMutableArray arrayWithArray:[fileInfo subarrayWithRange:NSMakeRange(0, kImageInfoIndexLock)]];
        [newFileInfo addObject:@(1)];
        [_images setObject:newFileInfo forKey:key];

        [self saveMetadata];
    }
}

// 解锁文件,可以被回收
- (void)unProtectFileWithKey:(NSString*)key
{
    NSParameterAssert(key != nil);

    if (![self isImageExistWithKey:key]) {
        return;
    }

    @synchronized(_images)
    {
        NSArray* fileInfo = [_images objectForKey:key];
        if ([fileInfo firstObject] == nil) {
            return;
        }

        // alread unlocked
        if ([fileInfo count] <= kImageInfoIndexLock) {
            return;
        }

        // name, type, width, height
        NSArray* newFileInfo = [fileInfo subarrayWithRange:NSMakeRange(0, kImageInfoIndexLock)];
        [_images setObject:newFileInfo forKey:key];

        [self saveMetadata];
    }
}

#pragma mark - Working with Metadata
- (void)saveMetadata
{
    static dispatch_queue_t __metadataQueue = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
		NSString *name = [NSString stringWithFormat:@"com.flyimage.imagemeta.%@", [[NSUUID UUID] UUIDString]];
		__metadataQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], NULL);
    });

    dispatch_async(__metadataQueue, ^{
		[_lock lock];
		
		NSData *data = [NSJSONSerialization dataWithJSONObject:[_images copy] options:kNilOptions error:NULL];
		BOOL fileWriteResult = [data writeToFile:_metaPath atomically:NO];
		if (fileWriteResult == NO) {
			FlyImageErrorLog(@"couldn't save metadata");
		}
		
		[_lock unlock];
    });
}

- (void)loadMetadata
{
    // load content from index file
    NSError* error;
    NSData* metadataData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:_metaPath] options:NSDataReadingMappedAlways error:&error];
    if (error != nil || metadataData == nil) {
        [self createMetadata];
        return;
    }

    NSDictionary* parsedObject = (NSDictionary*)[NSJSONSerialization JSONObjectWithData:metadataData options:kNilOptions error:&error];
    if (error != nil || parsedObject == nil) {
        [self createMetadata];
        return;
    }

    _images = [NSMutableDictionary dictionaryWithDictionary:parsedObject];
}

- (void)createMetadata
{
    _images = [NSMutableDictionary dictionaryWithCapacity:100];
}

@end


================================================
FILE: FlyImage/Core/FlyImageCacheProtocol.h
================================================
//
//  FlyImageCacheProtocol.h
//  Demo
//
//  Created by Norris Tong on 4/2/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#ifndef FlyImageCacheProtocol_h
#define FlyImageCacheProtocol_h

typedef void (^FlyImageCacheRetrieveBlock)(NSString* key, UIImage* image);

/**
 *  Common API for FlyImageCache and FlyImageIconCache.
 */
@protocol FlyImageCacheProtocol <NSObject>

/**
 *  Create an image cache with default meta path.
 */
+ (instancetype)sharedInstance;

/**
 *  Create an image cache with a specific meta path.
 *
 *  @param metaPath specific meta path, all the images will be saved into folder `metaPath/files`
 */
- (instancetype)initWithMetaPath:(NSString*)metaPath;

/**
 *  Get image from cache asynchronously.
 */
- (void)asyncGetImageWithKey:(NSString*)key
                   completed:(FlyImageCacheRetrieveBlock)completed;

/**
 *  Cancel geting an image from cache if the image has not already got.
 */
- (void)cancelGetImageWithKey:(NSString*)key;

/**
 *  Check if image exists in cache synchronized. NO delay.
 */
- (BOOL)isImageExistWithKey:(NSString*)key;

/**
 *  Remove an image from cache.
 */
- (void)removeImageWithKey:(NSString*)key;

/**
 *  Change the old key with a new key
 */
- (void)changeImageKey:(NSString*)oldKey
                newKey:(NSString*)newKey;

/**
 *  Remove all the images from the cache.
 */
- (void)purge;

@end

#endif /* FlyImageCacheProtocol_h */


================================================
FILE: FlyImage/Core/FlyImageDataFile.h
================================================
//
//  FlyImageDataFile.h
//  Demo
//
//  Created by Ye Tong on 3/18/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import <UIKit/UIKit.h>

/**
 *  Wrapper of data file, map the disk file to the memory.
 *
 *  Only support `append` operation, we can move the pointer to replace the data.
 *
 */
@interface FlyImageDataFile : NSObject

@property (nonatomic, assign, readonly) void* address;
@property (nonatomic, assign, readonly) off_t fileLength; // total length of the file.
@property (nonatomic, assign, readonly) off_t pointer; // append the data after the pointer. Default is 0.
@property (nonatomic, assign) size_t step; // Change the step value to increase the file length. Deafult is 1 byte.

- (instancetype)initWithPath:(NSString*)path;

- (BOOL)open;

- (void)close;

/**
 *  Check the file length, if it is not big enough, then increase the file length with step.
 *
 *  @param offset start position
 *  @param length data length
 *
 *  @return success or failed
 */
- (BOOL)prepareAppendDataWithOffset:(size_t)offset length:(size_t)length;

/**
 *  Append the data after pointer.
 *
 *  Must execute `prepareAppendDataWithOffset:length` first.
 *
 *  @param offset start position
 *  @param length data length
 *
 *  @return success or failed
 */
- (BOOL)appendDataWithOffset:(size_t)offset length:(size_t)length;

@end


================================================
FILE: FlyImage/Core/FlyImageDataFile.m
================================================
//
//  FlyImageDataFile.m
//  Demo
//
//  Created by Ye Tong on 3/18/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "FlyImageDataFile.h"
#import "FlyImageCache.h"
#import "FlyImageUtils.h"
#import <sys/mman.h>

@implementation FlyImageDataFile {
    NSString* _filePath;
    int _fileDescriptor;
    size_t _maxLength; // default is 100Mb.

    NSRecursiveLock* _lock;
}

- (instancetype)initWithPath:(NSString*)path
{
    if (self = [self init]) {
        _filePath = [path copy];
        _maxLength = 1024 * 1024 * 100;
        _step = 1;
        _pointer = 0;
        _lock = [[NSRecursiveLock alloc] init];
        _fileDescriptor = -1;
    }
    return self;
}

- (void)dealloc
{
    // should close the file if it's not be used again.
    [self close];
}

- (BOOL)open
{
    _fileDescriptor = open([_filePath fileSystemRepresentation], O_RDWR | O_CREAT, 0666);
    if (_fileDescriptor < 0) {
        FlyImageErrorLog(@"can't file at %@", _filePath);
        return NO;
    }

    _fileLength = lseek(_fileDescriptor, 0, SEEK_END);
    if (_fileLength == 0) {
        [self increaseFileLength:_step];
    } else {
        [self mmap];
    }

    return YES;
}

- (void)close
{
    if (_fileDescriptor < 0) {
        return;
    }

    [_lock lock];

    close(_fileDescriptor);
    _fileDescriptor = -1;

    // 取消内存映射
    [self munmap];

    [_lock unlock];
}

- (void)munmap
{
    if (_address == NULL) {
        return;
    }

    munmap(_address, (size_t)_fileLength);
    _address = NULL;
}

- (void)mmap
{
    _address = mmap(NULL, (size_t)_fileLength, (PROT_READ | PROT_WRITE), (MAP_FILE | MAP_SHARED), _fileDescriptor, 0);
}

- (BOOL)prepareAppendDataWithOffset:(size_t)offset length:(size_t)length
{
    NSAssert(_fileDescriptor > -1, @"open this file first.");

    [_lock lock];

    // can't exceed maxLength
    if (offset + length > _maxLength) {
        [_lock unlock];
        return NO;
    }

    // Check the file length, if it is not big enough, then increase the file length with step.
    if (offset + length > _fileLength) {
        size_t correctLength = ceill((length * 1.0 / _step)) * _step;
        if (![self increaseFileLength:correctLength]) {
            [_lock unlock];
            return NO;
        }
    }

    [_lock unlock];
    return YES;
}

- (BOOL)appendDataWithOffset:(size_t)offset length:(size_t)length
{
    NSAssert(_fileDescriptor > -1, @"open this file first.");

    [_lock lock];

    int result = msync(_address + offset, length, MS_SYNC);
    if (result < 0) {
        FlyImageErrorLog(@"append data failed");
        [_lock unlock];
        return NO;
    }

    // move the pointer
    if (offset + length > _pointer) {
        _pointer = offset + length;
    }

    [_lock unlock];

    return YES;
}

- (BOOL)increaseFileLength:(size_t)length
{
    [_lock lock];

    // cancel map first
    [self munmap];

    // change file length
    int result = ftruncate(_fileDescriptor, _fileLength + length);
    if (result < 0) {
        FlyImageErrorLog(@"can't truncate data file");
        [_lock unlock];
        return NO;
    }

    // remap
    _fileLength = lseek(_fileDescriptor, 0, SEEK_END);
    [self mmap];

    [_lock unlock];

    return YES;
}

@end


================================================
FILE: FlyImage/Core/FlyImageDataFileManager.h
================================================
//
//  FlyImageDataFileManager.h
//  Demo
//
//  Created by Ye Tong on 3/22/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "FlyImageDataFile.h"

/**
 *  Manager of FlyImageDataFile. In charge of creating and deleting data file.
 */
@interface FlyImageDataFileManager : NSObject

@property (nonatomic, strong, readonly) NSString* folderPath; // folder saved data files.
@property (nonatomic, assign, readonly) BOOL isDiskFull; // Default is NO.

- (instancetype)initWithFolderPath:(NSString*)folderPath;

/**
 *  Create a `FlyImageDataFile` if it doesn't exist.
 */
- (FlyImageDataFile*)createFileWithName:(NSString*)name;

/**
 *  Add an exist file.
 */
- (void)addExistFileName:(NSString*)name;

/**
 *  Check the file whether exist or not, no delay.
 */
- (BOOL)isFileExistWithName:(NSString*)name;

/**
 *  Get a `FlyImageDataFile` if it exists.
 */
- (FlyImageDataFile*)retrieveFileWithName:(NSString*)name;

/**
 *  Remove data file
 */
- (void)removeFileWithName:(NSString*)name;

/**
 *  Create a `FlyImageDataFile` async.
 */
- (void)asyncCreateFileWithName:(NSString*)name completed:(void (^)(FlyImageDataFile* dataFile))completed;

/**
 *  Remove all the data files, except some special files.
 *
 *  @param names     except files' names
 *  @param toSize    expected size of the folder
 *  @param completed callback
 */
- (void)purgeWithExceptions:(NSArray*)names
                     toSize:(NSUInteger)toSize
                  completed:(void (^)(NSUInteger fileCount, NSUInteger totalSize))completed;

/**
 *  Calculate the folder size.
 */
- (void)calculateSizeWithCompletionBlock:(void (^)(NSUInteger fileCount, NSUInteger totalSize))block;

/**
 *  Free space left in the system space.
 */
- (void)freeDiskSpaceWithCompletionBlock:(void (^)(NSUInteger freeSize))block;

@end


================================================
FILE: FlyImage/Core/FlyImageDataFileManager.m
================================================
//
//  FlyImageDataFileManager.m
//  Demo
//
//  Created by Ye Tong on 3/22/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "FlyImageDataFileManager.h"
#import "FlyImageUtils.h"

@implementation FlyImageDataFileManager {
    NSFileManager* _fileManager;
    dispatch_queue_t _fileQueue;
    NSMutableDictionary* _fileNames;
    NSMutableDictionary* _creatingFiles;
}

- (instancetype)initWithFolderPath:(NSString*)folderPath
{
    if (self = [self init]) {
        _folderPath = [folderPath copy];

        // create a unique queue
        NSString* queueName = [@"com.flyimage.filemanager." stringByAppendingString:[[NSUUID UUID] UUIDString]];
        _fileQueue = dispatch_queue_create([queueName cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_SERIAL);

        dispatch_sync(_fileQueue, ^{
            _fileManager = [NSFileManager new];
            
            [self makeDirectory];
            [self listDirectory];
            [self checkDiskStatus];
        });
    }
    return self;
}

- (void)makeDirectory
{
    BOOL isFolderExist = [_fileManager fileExistsAtPath:_folderPath];
    if (!isFolderExist) {
        [_fileManager createDirectoryAtPath:_folderPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
}

- (void)listDirectory
{
    _creatingFiles = [[NSMutableDictionary alloc] init];

    NSArray* filenames = [_fileManager contentsOfDirectoryAtPath:_folderPath error:nil];
    _fileNames = [[NSMutableDictionary alloc] initWithCapacity:[filenames count]];
    for (NSString* filename in filenames) {
        [_fileNames setObject:@(1) forKey:filename];
    }
}

// Execute in the _fileQueue
- (void)checkDiskStatus
{
    NSDictionary* fileAttributes = [_fileManager attributesOfFileSystemForPath:@"/" error:nil];
    unsigned long long freeSize = [[fileAttributes objectForKey:NSFileSystemFreeSize] unsignedLongLongValue];

    // set disk is full when free size is less than 20Mb
    _isDiskFull = freeSize < 1024 * 1024 * 20;
}

- (void)asyncCreateFileWithName:(NSString*)name completed:(void (^)(FlyImageDataFile* dataFile))completed
{
    NSParameterAssert(name);
    NSParameterAssert(completed);

    // already exist
    NSString* filePath = [_folderPath stringByAppendingPathComponent:name];
    if ([self isFileExistWithName:name]) {
        FlyImageDataFile* file = [[FlyImageDataFile alloc] initWithPath:filePath];
        completed(file);
        return;
    }

    // can't add more
    if (_isDiskFull) {
        completed(nil);
        return;
    }

    // save all the blocks into _creatingFiles, waiting for callback
    @synchronized(_creatingFiles)
    {
        if ([_creatingFiles objectForKey:name] == nil) {
            [_creatingFiles setObject:[NSMutableArray arrayWithObject:completed] forKey:name];
        } else {
            NSMutableArray* blocks = [_creatingFiles objectForKey:name];
            [blocks addObject:completed];
        }
    }

    dispatch_async(_fileQueue, ^{
        
        NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
        [attributes setValue:NSFileProtectionCompleteUnlessOpen forKeyPath:NSFileProtectionKey];
        
        BOOL success = [_fileManager createFileAtPath:filePath contents:nil attributes:attributes];
        if ( !success ) {
            FlyImageErrorLog(@"can't create file at path %@", filePath);
            
			// check if the disk is full
            [self checkDiskStatus];
            
            [self afterCreateFile:nil name:name];
            return;
        }
        
        // update index
        @synchronized (_fileNames) {
            [_fileNames setObject:@(1) forKey:name];
        }
        
        FlyImageDataFile *file = [[FlyImageDataFile alloc] initWithPath:filePath];
        [self afterCreateFile:file name:name];
    });
}

- (void)afterCreateFile:(FlyImageDataFile*)file name:(NSString*)name
{

    NSArray* blocks = nil;
    @synchronized(_creatingFiles)
    {
        blocks = [[_creatingFiles objectForKey:name] copy];
        [_creatingFiles removeObjectForKey:name];
    }

    dispatch_main_sync_safe(^{
        for (  void (^block)(FlyImageDataFile *dataFile) in blocks) {
            block( file );
        }
    });
}

- (void)addExistFileName:(NSString*)name
{
    NSParameterAssert(name);

    @synchronized(_fileNames)
    {
        [_fileNames setObject:@(1) forKey:name];
    }
}

- (FlyImageDataFile*)createFileWithName:(NSString*)name
{
    NSParameterAssert(name);

    // already exist
    NSString* filePath = [_folderPath stringByAppendingPathComponent:name];
    if ([self isFileExistWithName:name]) {
        return [[FlyImageDataFile alloc] initWithPath:filePath];
    }

    // can't add more
    if (_isDiskFull) {
        return nil;
    }

    NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
    [attributes setValue:NSFileProtectionCompleteUnlessOpen forKeyPath:NSFileProtectionKey];

    BOOL success = [_fileManager createFileAtPath:filePath contents:nil attributes:attributes];
    if (!success) {
        FlyImageErrorLog(@"can't create file at path %@", filePath);

        // check if the disk is full
        [self checkDiskStatus];

        return nil;
    }

    // update index
    @synchronized(_fileNames)
    {
        [_fileNames setObject:@(1) forKey:name];
    }

    return [[FlyImageDataFile alloc] initWithPath:filePath];
}

- (BOOL)isFileExistWithName:(NSString*)name
{
    NSParameterAssert(name);

    return [_fileNames objectForKey:name] != nil;
}

- (FlyImageDataFile*)retrieveFileWithName:(NSString*)name
{
    NSParameterAssert(name);

    if (![self isFileExistWithName:name]) {
        return nil;
    }

    NSString* filePath = [_folderPath stringByAppendingPathComponent:name];
    FlyImageDataFile* file = [[FlyImageDataFile alloc] initWithPath:filePath];

    return file;
}

- (void)removeFileWithName:(NSString*)name
{
    NSParameterAssert(name);

    if (![self isFileExistWithName:name]) {
        return;
    }

    // remove from the indexes first
    @synchronized(_fileNames)
    {
        [_fileNames removeObjectForKey:name];
    }

    // delete file
    dispatch_async(_fileQueue, ^{
        [_fileManager removeItemAtPath:[_folderPath stringByAppendingPathComponent:name] error:nil];
        
        [self checkDiskStatus];
    });
}

- (void)purgeWithExceptions:(NSArray*)names
                     toSize:(NSUInteger)toSize
                  completed:(void (^)(NSUInteger fileCount, NSUInteger totalSize))completed
{
    dispatch_async(_fileQueue, ^{
        
        // from array to dictionary
        NSMutableDictionary *exceptions = [[NSMutableDictionary alloc] initWithCapacity:[names count]];
        for (NSString *name in names) {
            [exceptions setObject:@(1) forKey:name];
        }
        
        NSUInteger totalSize = (NSUInteger)[[_fileManager attributesOfItemAtPath:_folderPath error:nil] fileSize];
        
        NSURL *folderURL = [NSURL fileURLWithPath:_folderPath isDirectory:YES];
        NSArray *resourceKeys = @[NSURLIsDirectoryKey, NSURLNameKey, NSURLTotalFileAllocatedSizeKey];
        
        // This enumerator prefetches useful properties for our cache files.
        NSDirectoryEnumerator *enumerator = [_fileManager enumeratorAtURL:folderURL
                                               includingPropertiesForKeys:resourceKeys
                                                                  options:NSDirectoryEnumerationSkipsHiddenFiles
                                                             errorHandler:NULL];
        
        // TODO SORT
        NSMutableArray *urlsToDelete = [[NSMutableArray alloc] init];
        NSMutableArray *namesToDelete = [[NSMutableArray alloc] init];
        for (NSURL *fileURL in enumerator) {
            NSNumber *isDirectory;
            [fileURL getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:nil];
            
            if ([isDirectory boolValue]) {
                continue;
            }
            
            NSString *fileName;
            [fileURL getResourceValue:&fileName forKey:NSURLNameKey error:nil];
            
            // dont remove file in exceptions
            if ( [exceptions objectForKey:fileName] != nil ) {
                continue;
            }
            
            NSNumber *fileSize;
            [fileURL getResourceValue:&fileSize forKey:NSURLTotalFileAllocatedSizeKey error:nil];
            
            // dont remove more files
            totalSize -= [fileSize unsignedLongValue];
            if ( totalSize <= toSize ) {
                break;
            }
            
            [urlsToDelete addObject:fileURL];
            [namesToDelete addObject:fileName];
        }
        
        // remove file and index
        for (NSURL *fileURL in urlsToDelete) {
            [_fileManager removeItemAtURL:fileURL error:nil];
        }
        @synchronized (_fileNames) {
            for (NSString *fileName in namesToDelete) {
                [_fileNames removeObjectForKey:fileName];
            }
        }
        
        [self checkDiskStatus];
        
        if ( completed != nil ) {
            NSUInteger fileCount = [_fileNames count];
            completed( fileCount, fileCount == 0 ? 0 : totalSize );
        }
    });
}

- (void)calculateSizeWithCompletionBlock:(void (^)(NSUInteger fileCount, NSUInteger totalSize))block
{
    NSParameterAssert(block);

    dispatch_async(_fileQueue, ^{
        // dont count self folder
        NSUInteger fileCount = MAX(0, [[[_fileManager enumeratorAtPath:_folderPath] allObjects] count] - 1);
        NSUInteger totalSize = (NSUInteger)[[_fileManager attributesOfItemAtPath:_folderPath error:nil] fileSize];
        
        dispatch_main_async_safe(^{
            block( fileCount, fileCount == 0 ? 0 : totalSize );
        });
    });
}

- (void)freeDiskSpaceWithCompletionBlock:(void (^)(NSUInteger freeSize))block
{
    NSParameterAssert(block);

    dispatch_async(_fileQueue, ^{
        NSDictionary *fileAttributes = [_fileManager attributesOfFileSystemForPath:@"/" error:nil];
        NSUInteger freeSize = (NSUInteger)[[fileAttributes objectForKey:NSFileSystemFreeSize] unsignedLongLongValue];
        
        dispatch_main_async_safe(^{
            block( freeSize );
        });
    });
}

@end


================================================
FILE: FlyImage/Core/FlyImageDecoder.h
================================================
//
//  FlyImageDecoder.h
//  Demo
//
//  Created by Ye Tong on 3/22/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "FlyImageUtils.h"

/**
 *  Decode image file.
 */
@interface FlyImageDecoder : NSObject

/**
 *  Convert memory buffer to icon.
 *
 *  @param bytes    memory file
 *  @param offset   offset position at the memory file
 *  @param length   size of memory buffer
 *  @param drawSize render size
 */
- (UIImage*)iconImageWithBytes:(void*)bytes
                        offset:(size_t)offset
                        length:(size_t)length
                      drawSize:(CGSize)drawSize;

/**
 *  Decode a single image file.
 *
 *  @param file            FlyImageDataFile instance
 *  @param contentType     only support PNG/JPEG
 *  @param bytes           address of the memory
 *  @param length          file size
 *  @param drawSize        drawing size, not image  size
 *  @param contentsGravity contentsGravity of the image
 *  @param cornerRadius    cornerRadius of the image
 */
- (UIImage*)imageWithFile:(void*)file
              contentType:(ImageContentType)contentType
                    bytes:(void*)bytes
                   length:(size_t)length
                 drawSize:(CGSize)drawSize
          contentsGravity:(NSString* const)contentsGravity
             cornerRadius:(CGFloat)cornerRadius;

#ifdef FLYIMAGE_WEBP
- (UIImage*)imageWithWebPData:(NSData*)imageData hasAlpha:(BOOL*)hasAlpha;
#endif

@end


================================================
FILE: FlyImage/Core/FlyImageDecoder.m
================================================
//
//  FlyImageDecoder.m
//  Demo
//
//  Created by Ye Tong on 3/22/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "FlyImageDecoder.h"
#ifdef FLYIMAGE_WEBP
#import "webp/decode.h"
#endif

static void __ReleaseAsset(void* info, const void* data, size_t size)
{
    if (info != NULL) {
        CFRelease(info); // will cause dealloc of FlyImageDataFile
    }
}

#ifdef FLYIMAGE_WEBP
// This gets called when the UIImage gets collected and frees the underlying image.
static void free_image_data(void* info, const void* data, size_t size)
{
    if (info != NULL) {
        WebPFreeDecBuffer(&(((WebPDecoderConfig*)info)->output));
        free(info);
    }

    if (data != NULL) {
        free((void*)data);
    }
}
#endif

@implementation FlyImageDecoder

- (UIImage*)iconImageWithBytes:(void*)bytes
                        offset:(size_t)offset
                        length:(size_t)length
                      drawSize:(CGSize)drawSize
{

    // Create CGImageRef whose backing store *is* the mapped image table entry. We avoid a memcpy this way.
    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, bytes + offset, length, __ReleaseAsset);

    CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
    NSInteger bitsPerComponent = 8;
    NSInteger bitsPerPixel = 4 * 8;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    static NSInteger bytesPerPixel = 4;
    static float kAlignment = 64;
    CGFloat screenScale = [FlyImageUtils contentsScale];
    size_t bytesPerRow = ceil((drawSize.width * screenScale * bytesPerPixel) / kAlignment) * kAlignment;

    CGImageRef imageRef = CGImageCreate(drawSize.width * screenScale,
                                        drawSize.height * screenScale,
                                        bitsPerComponent,
                                        bitsPerPixel,
                                        bytesPerRow,
                                        colorSpace,
                                        bitmapInfo,
                                        dataProvider,
                                        NULL,
                                        false,
                                        kCGRenderingIntentDefault);

    CGDataProviderRelease(dataProvider);
    CGColorSpaceRelease(colorSpace);

    if (imageRef == nil) {
        return nil;
    }

    UIImage* image = [[UIImage alloc] initWithCGImage:imageRef
                                                scale:screenScale
                                          orientation:UIImageOrientationUp];
    CGImageRelease(imageRef);

    return image;
}

- (CGImageRef)imageRefWithFile:(void*)file
                   contentType:(ImageContentType)contentType
                         bytes:(void*)bytes
                        length:(size_t)length
{
    if (contentType == ImageContentTypeUnknown || contentType == ImageContentTypeGif || contentType == ImageContentTypeTiff) {
        return nil;
    }

    // Create CGImageRef whose backing store *is* the mapped image table entry. We avoid a memcpy this way.
    CGDataProviderRef dataProvider = nil;
    CGImageRef imageRef = nil;
    if (contentType == ImageContentTypeJPEG) {
        CFRetain(file);
        dataProvider = CGDataProviderCreateWithData(file, bytes, length, __ReleaseAsset);
        imageRef = CGImageCreateWithJPEGDataProvider(dataProvider, NULL, YES, kCGRenderingIntentDefault);

    } else if (contentType == ImageContentTypePNG) {
        CFRetain(file);
        dataProvider = CGDataProviderCreateWithData(file, bytes, length, __ReleaseAsset);
        imageRef = CGImageCreateWithPNGDataProvider(dataProvider, NULL, YES, kCGRenderingIntentDefault);

    } else if (contentType == ImageContentTypeWebP) {
#ifdef FLYIMAGE_WEBP
        // `WebPGetInfo` weill return image width and height
        int width = 0, height = 0;
        if (!WebPGetInfo(bytes, length, &width, &height)) {
            return nil;
        }

        WebPDecoderConfig* config = malloc(sizeof(WebPDecoderConfig));
        if (!WebPInitDecoderConfig(config)) {
            return nil;
        }

        config->options.no_fancy_upsampling = 1;
        config->options.bypass_filtering = 1;
        config->options.use_threads = 1;
        config->output.colorspace = MODE_RGBA;

        // Decode the WebP image data into a RGBA value array
        VP8StatusCode decodeStatus = WebPDecode(bytes, length, config);
        if (decodeStatus != VP8_STATUS_OK) {
            return nil;
        }

        // Construct UIImage from the decoded RGBA value array
        uint8_t* data = WebPDecodeRGBA(bytes, length, &width, &height);
        dataProvider = CGDataProviderCreateWithData(config, data, config->options.scaled_width * config->options.scaled_height * 4, free_image_data);

        CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
        CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast;
        CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

        imageRef = CGImageCreate(width, height, 8, 32, 4 * width, colorSpaceRef, bitmapInfo, dataProvider, NULL, YES, renderingIntent);
#endif
    }

    if (dataProvider != nil) {
        CGDataProviderRelease(dataProvider);
    }

    return imageRef;
}

- (UIImage*)imageWithFile:(void*)file
              contentType:(ImageContentType)contentType
                    bytes:(void*)bytes
                   length:(size_t)length
                 drawSize:(CGSize)drawSize
          contentsGravity:(NSString* const)contentsGravity
             cornerRadius:(CGFloat)cornerRadius
{

    CGImageRef imageRef = [self imageRefWithFile:file contentType:contentType bytes:bytes length:length];
    if (imageRef == nil) {
        return nil;
    }

    CGSize imageSize = CGSizeMake(CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
    CGFloat contentsScale = 1;
    if (drawSize.width < imageSize.width && drawSize.height < imageSize.height) {
        contentsScale = [FlyImageUtils contentsScale];
    }
    CGSize contextSize = CGSizeMake(drawSize.width * contentsScale, drawSize.height * contentsScale);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);

    int infoMask = (bitmapInfo & kCGBitmapAlphaInfoMask);
    BOOL anyNonAlpha = (infoMask == kCGImageAlphaNone || infoMask == kCGImageAlphaNoneSkipFirst || infoMask == kCGImageAlphaNoneSkipLast);

    // CGBitmapContextCreate doesn't support kCGImageAlphaNone with RGB.
    // https://developer.apple.com/library/mac/#qa/qa1037/_index.html
    if (cornerRadius > 0) {
        bitmapInfo &= kCGImageAlphaPremultipliedLast;
    } else if (infoMask == kCGImageAlphaNone && CGColorSpaceGetNumberOfComponents(colorSpace) > 1) {
        // Unset the old alpha info.
        bitmapInfo &= ~kCGBitmapAlphaInfoMask;

        // Set noneSkipFirst.
        bitmapInfo |= kCGImageAlphaNoneSkipFirst;
    }
    // Some PNGs tell us they have alpha but only 3 components. Odd.
    else if (!anyNonAlpha && CGColorSpaceGetNumberOfComponents(colorSpace) == 3) {
        // Unset the old alpha info.
        bitmapInfo &= ~kCGBitmapAlphaInfoMask;
        bitmapInfo |= kCGImageAlphaPremultipliedFirst;
    }

    // It calculates the bytes-per-row based on the bitsPerComponent and width arguments.
    static NSInteger bytesPerPixel = 4;
    static float kAlignment = 64;
    size_t bytesPerRow = ceil((contextSize.width * bytesPerPixel) / kAlignment) * kAlignment;

    CGContextRef context = CGBitmapContextCreate(NULL, contextSize.width, contextSize.height, CGImageGetBitsPerComponent(imageRef), bytesPerRow, colorSpace, bitmapInfo);
    CGColorSpaceRelease(colorSpace);

    // If failed, return undecompressed image
    if (!context) {
        UIImage* image = [[UIImage alloc] initWithCGImage:imageRef
                                                    scale:contentsScale
                                              orientation:UIImageOrientationUp];
        CGImageRelease(imageRef);
        return image;
    }

    CGContextScaleCTM(context, contentsScale, contentsScale);
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);

    CGRect contextBounds = CGRectMake(0, 0, drawSize.width, drawSize.height);

    // Clip to a rounded rect
    if (cornerRadius > 0) {
        CGPathRef path = _FICDCreateRoundedRectPath(contextBounds, cornerRadius);
        CGContextAddPath(context, path);
        CFRelease(path);
        CGContextEOClip(context);
    }

    CGContextDrawImage(context, _FlyImageCalcDrawBounds(imageSize,
                                                        drawSize,
                                                        contentsGravity),
                       imageRef);

    CGImageRef decompressedImageRef = CGBitmapContextCreateImage(context);
    CGContextRelease(context);

    UIImage* decompressedImage = [UIImage imageWithCGImage:decompressedImageRef
                                                     scale:contentsScale
                                               orientation:UIImageOrientationUp];

    CGImageRelease(decompressedImageRef);
    CGImageRelease(imageRef);

    return decompressedImage;
}

#ifdef FLYIMAGE_WEBP
- (UIImage*)imageWithWebPData:(NSData*)imageData hasAlpha:(BOOL*)hasAlpha
{

    // `WebPGetInfo` weill return image width and height
    int width = 0, height = 0;
    if (!WebPGetInfo(imageData.bytes, imageData.length, &width, &height)) {
        return nil;
    }

    WebPDecoderConfig* config = malloc(sizeof(WebPDecoderConfig));
    if (!WebPInitDecoderConfig(config)) {
        return nil;
    }

    config->options.no_fancy_upsampling = 1;
    config->options.bypass_filtering = 1;
    config->options.use_threads = 1;
    config->output.colorspace = MODE_RGBA;

    // Decode the WebP image data into a RGBA value array
    VP8StatusCode decodeStatus = WebPDecode(imageData.bytes, imageData.length, config);
    if (decodeStatus != VP8_STATUS_OK) {
        return nil;
    }

    // set alpha value
    if (hasAlpha != nil) {
        *hasAlpha = config->input.has_alpha;
    }

    // Construct UIImage from the decoded RGBA value array
    uint8_t* data = WebPDecodeRGBA(imageData.bytes, imageData.length, &width, &height);
    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(config, data, config->options.scaled_width * config->options.scaled_height * 4, free_image_data);

    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

    CGImageRef imageRef = CGImageCreate(width, height, 8, 32, 4 * width, colorSpaceRef, bitmapInfo, dataProvider, NULL, YES, renderingIntent);
    UIImage* decodeImage = [UIImage imageWithCGImage:imageRef];

    UIGraphicsBeginImageContextWithOptions(decodeImage.size, !config->input.has_alpha, 1);
    [decodeImage drawInRect:CGRectMake(0, 0, decodeImage.size.width, decodeImage.size.height)];
    UIImage* decompressedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return decompressedImage;
}
#endif

@end


================================================
FILE: FlyImage/Core/FlyImageDownloader.h
================================================
//
//  FlyImageDownloader.h
//  Demo
//
//  Created by Ye Tong on 3/22/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef void (^FlyImageDownloadProgressBlock)(float progress);
typedef void (^FlyImageDownloadSuccessBlock)(NSURLRequest* request, NSURL* filePath);
typedef void (^FlyImageDownloadFailedBlock)(NSURLRequest* request, NSError* error);
typedef NSUUID FlyImageDownloadHandlerId; // Unique ID of handler

@class FlyImageDownloader;
@protocol FlyImageDownloaderDelegate <NSObject>

@optional
/**
 *  Callback before sending request.
 */
- (void)FlyImageDownloader:(FlyImageDownloader*)manager
           willSendRequest:(NSURLRequest*)request;

/**
 *  Callback after complete download.
 */
- (void)FlyImageDownloader:(FlyImageDownloader*)manager
        didReceiveResponse:(NSURLResponse*)response
                  filePath:(NSURL*)filePath
                     error:(NSError*)error
                   request:(NSURLRequest*)request;

/**
 *  Callback after cancel some request.
 */
- (void)FlyImageDownloader:(FlyImageDownloader*)manager
         willCancelRequest:(NSURLRequest*)request;

@end

@interface FlyImageDownloader : NSObject

@property (nonatomic, weak) id<FlyImageDownloaderDelegate> delegate;
@property (nonatomic, copy) NSString* destinationPath;
@property (nonatomic, assign) NSInteger maxDownloadingCount; // Default is 5;

/**
 *  Create a FlyImageDownloader with a default destination path.
 */
+ (instancetype)sharedInstance;

/**
 *  Create a FlyImageDownloader with a specific destination path.
 */
- (instancetype)initWithDestinationPath:(NSString*)destinationPath;

- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request;

- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request
                                                 success:(FlyImageDownloadSuccessBlock)success
                                                  failed:(FlyImageDownloadFailedBlock)failed;

/**
 *  Send a download request with callbacks
 */
- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request
                                                progress:(FlyImageDownloadProgressBlock)progress
                                                 success:(FlyImageDownloadSuccessBlock)success
                                                  failed:(FlyImageDownloadFailedBlock)failed;

/**
 *  Cancel a downloading request.
 *
 *  @param handlerId can't be nil
 */
- (void)cancelDownloadHandler:(FlyImageDownloadHandlerId*)handlerId;

@end


================================================
FILE: FlyImage/Core/FlyImageDownloader.m
================================================
//
//  FlyImageDownloader.m
//  Demo
//
//  Created by Ye Tong on 3/22/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "FlyImageDownloader.h"
#import "AFNetworking.h"
#import "FlyImageUtils.h"
#import "FlyImageDataFileManager.h"
#import "FlyImageCache.h"
#import <objc/runtime.h>
#import <CommonCrypto/CommonDigest.h>

@interface FlyImageDownloaderResponseHandler : NSObject
@property (nonatomic, strong) NSUUID* uuid;
@property (nonatomic, strong) FlyImageDownloadProgressBlock processingBlock;
@property (nonatomic, strong) FlyImageDownloadSuccessBlock successBlock;
@property (nonatomic, strong) FlyImageDownloadFailedBlock failedBlock;
@end

@implementation FlyImageDownloaderResponseHandler

- (instancetype)initWithUUID:(NSUUID*)uuid
                    progress:(FlyImageDownloadProgressBlock)progress
                     success:(FlyImageDownloadSuccessBlock)success
                      failed:(FlyImageDownloadFailedBlock)failed
{
    if (self = [self init]) {
        self.uuid = uuid;
        self.processingBlock = progress;
        self.successBlock = success;
        self.failedBlock = failed;
    }
    return self;
}

@end

@interface FlyImageDownloaderMergedTask : NSObject
@property (nonatomic, strong) NSString* identifier;
@property (nonatomic, strong) NSMutableArray* handlers;
@property (nonatomic, strong) NSURLSessionDownloadTask* task;
@end

@implementation FlyImageDownloaderMergedTask

- (instancetype)initWithIdentifier:(NSString*)identifier task:(NSURLSessionDownloadTask*)task
{
    if (self = [self init]) {
        self.identifier = identifier;
        self.task = task;
        self.handlers = [[NSMutableArray alloc] init];
    }
    return self;
}

- (void)addResponseHandler:(FlyImageDownloaderResponseHandler*)handler
{
    [self.handlers addObject:handler];
}

- (void)removeResponseHandler:(FlyImageDownloaderResponseHandler*)handler
{
    [self.handlers removeObject:handler];
}

- (void)clearHandlers
{
    [self.handlers removeAllObjects];
}

@end

@interface NSString (Extension)
- (NSString*)md5;
@end

@implementation NSString (Extension)
- (NSString*)md5
{
    const char* cStr = [self UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(cStr, (CC_LONG)strlen(cStr), result); // This is the md5 call
    return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
                                      result[0],
                                      result[1],
                                      result[2],
                                      result[3],
                                      result[4],
                                      result[5],
                                      result[6],
                                      result[7],
                                      result[8],
                                      result[9],
                                      result[10],
                                      result[11],
                                      result[12],
                                      result[13],
                                      result[14],
                                      result[15]];
}
@end

@interface FlyImageDownloader ()
@property (nonatomic, strong) NSMutableDictionary* downloadFile;
@property (nonatomic, strong) NSMutableDictionary* mergedTasks;
@property (nonatomic, strong) NSMutableArray* queuedMergedTasks;
@property (nonatomic, assign) NSInteger activeRequestCount;
@property (nonatomic, strong) dispatch_queue_t synchronizationQueue;
@property (nonatomic, strong) dispatch_queue_t responseQueue;
@end

@implementation FlyImageDownloader {
    AFURLSessionManager* _sessionManager;
}

+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    static FlyImageDownloader* __instance = nil;
    dispatch_once(&onceToken, ^{
		NSString *folderPath = [FlyImageCache sharedInstance].dataFileManager.folderPath;
		__instance = [[[self class] alloc] initWithDestinationPath:folderPath];
    });

    return __instance;
}

- (instancetype)initWithDestinationPath:(NSString*)destinationPath
{
    if (self = [self init]) {

        _maxDownloadingCount = 5;
        _mergedTasks = [[NSMutableDictionary alloc] initWithCapacity:_maxDownloadingCount];
        _queuedMergedTasks = [[NSMutableArray alloc] initWithCapacity:_maxDownloadingCount];

        _destinationPath = [destinationPath copy];

        NSString* name = [NSString stringWithFormat:@"com.flyimage.imagedownloader.synchronizationqueue-%@", [[NSUUID UUID] UUIDString]];
        self.synchronizationQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_SERIAL);

        name = [NSString stringWithFormat:@"com.flyimage.imagedownloader.responsequeue-%@", [[NSUUID UUID] UUIDString]];
        self.responseQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_CONCURRENT);

        NSString* configurationIdentifier = [NSString stringWithFormat:@"com.flyimage.downloadsession.%@", [[NSUUID UUID] UUIDString]];
        NSURLSessionConfiguration* configuration = [FlyImageDownloader configurationWithIdentifier:configurationIdentifier];
        _sessionManager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
    }
    return self;
}

+ (NSURLSessionConfiguration*)configurationWithIdentifier:(NSString*)identifier
{
    NSURLSessionConfiguration* configuration;
#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)
    configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
#else
    configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier];
#endif

    configuration.HTTPShouldSetCookies = YES;
    configuration.HTTPShouldUsePipelining = NO;

    configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
    configuration.allowsCellularAccess = YES;

    return configuration;
}

- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request
{
    return [self downloadImageForURLRequest:request
                                   progress:nil
                                    success:nil
                                     failed:nil];
}

- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request
                                                 success:(FlyImageDownloadSuccessBlock)success
                                                  failed:(FlyImageDownloadFailedBlock)failed
{
    return [self downloadImageForURLRequest:request
                                   progress:nil
                                    success:success
                                     failed:failed];
}

- (FlyImageDownloadHandlerId*)downloadImageForURLRequest:(NSURLRequest*)request
                                                progress:(FlyImageDownloadProgressBlock)progress
                                                 success:(FlyImageDownloadSuccessBlock)success
                                                  failed:(FlyImageDownloadFailedBlock)failed
{
    NSParameterAssert(request != nil);

    __block FlyImageDownloadHandlerId* handlerId = nil;
    dispatch_sync(_synchronizationQueue, ^{
        if (request.URL.absoluteString == nil) {
            if (failed) {
                NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorBadURL userInfo:nil];
                dispatch_main_sync_safe(^{
                    failed(request, error);
                });
            }
            return;
        }

        NSString *identifier = [request.URL.absoluteString md5];
        handlerId = [NSUUID UUID];
        
        // 1) Append the success and failure blocks to a pre-existing request if it already exists
        FlyImageDownloaderMergedTask *existingMergedTask = self.mergedTasks[identifier];
        if (existingMergedTask != nil) {
            FlyImageDownloaderResponseHandler *handler = [[FlyImageDownloaderResponseHandler alloc]
                                                          initWithUUID:handlerId
                                                          progress:progress
                                                          success:success
                                                          failed:failed];
            [existingMergedTask addResponseHandler:handler];
            return;
        }
        
        __weak __typeof__(self) weakSelf = self;
        NSURLSessionDownloadTask *task =
        [_sessionManager downloadTaskWithRequest:request
                                        progress:^(NSProgress * _Nonnull downloadProgress) {
											dispatch_async(weakSelf.responseQueue, ^{
												FlyImageDownloaderMergedTask *existingMergedTask = weakSelf.mergedTasks[identifier];
												for (FlyImageDownloaderResponseHandler *hanlder in existingMergedTask.handlers) {
													if ( hanlder.processingBlock != nil ) {
														dispatch_main_async_safe(^{
															hanlder.processingBlock( downloadProgress.fractionCompleted );
														});
													}
												}
											});
										}
                                     destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
                                         return [NSURL fileURLWithPath:[_destinationPath stringByAppendingPathComponent:identifier]];
                                     }
                               completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
								   dispatch_async(weakSelf.responseQueue, ^{
									   __strong __typeof__(weakSelf) strongSelf = weakSelf;
									   if ( [_delegate respondsToSelector:@selector(FlyImageDownloader:didReceiveResponse:filePath:error:request:)] ) {
										   dispatch_main_sync_safe(^{
											   [_delegate FlyImageDownloader:strongSelf
															   didReceiveResponse:response
																		 filePath:filePath
																			error:error
																		  request:request];
										   });
									   }
									   
									   FlyImageDownloaderMergedTask *mergedTask = strongSelf.mergedTasks[identifier];
									   if (error != nil) {
										   for (FlyImageDownloaderResponseHandler *handler in mergedTask.handlers) {
											   if (handler.failedBlock) {
												   handler.failedBlock(request, error);
											   }
										   }
										   
										   // remove error file
										   [[NSFileManager defaultManager] removeItemAtURL:filePath error:nil];
									   }else{
										   for (FlyImageDownloaderResponseHandler *handler in mergedTask.handlers) {
											   if (handler.successBlock) {
												   handler.successBlock(request, filePath);
											   }
										   }
									   }
									   
									   // remove exist task
									   [strongSelf.mergedTasks removeObjectForKey:identifier];
									   
									   [strongSelf safelyDecrementActiveTaskCount];
									   [strongSelf safelyStartNextTaskIfNecessary];
								   });
                               }];
        
        // 4) Store the response handler for use when the request completes
		existingMergedTask = [[FlyImageDownloaderMergedTask alloc] initWithIdentifier:identifier task:task];
        self.mergedTasks[ identifier ] = existingMergedTask;
        
        FlyImageDownloaderResponseHandler *handler = [[FlyImageDownloaderResponseHandler alloc]
                                                      initWithUUID:handlerId
                                                      progress:progress
                                                      success:success
                                                      failed:failed];
        [existingMergedTask addResponseHandler:handler];
        
        // 5) Either start the request or enqueue it depending on the current active request count
        if ([self isActiveRequestCountBelowMaximumLimit]) {
            [self startMergedTask:existingMergedTask];
        } else {
            [self enqueueMergedTask:existingMergedTask];
        }
    });

    return handlerId;
}

- (void)cancelDownloadHandler:(FlyImageDownloadHandlerId*)handlerId
{
    NSParameterAssert(handlerId != nil);

    dispatch_sync(_synchronizationQueue, ^{
        
        FlyImageDownloaderMergedTask *matchedTask = nil;
        FlyImageDownloaderResponseHandler *matchedHandler = nil;
        
        for (NSString *URLIdentifier in self.mergedTasks) {
            FlyImageDownloaderMergedTask *mergedTask = self.mergedTasks[ URLIdentifier ];
            for (FlyImageDownloaderResponseHandler *handler in mergedTask.handlers) {
                if ( [handler.uuid isEqual:handlerId] ) {
                    matchedHandler = handler;
                    matchedTask = mergedTask;
                    break;
                }
            }
        }
        
        if ( matchedTask == nil ) {
            for (FlyImageDownloaderMergedTask *mergedTask in _queuedMergedTasks) {
                for (FlyImageDownloaderResponseHandler *handler in mergedTask.handlers) {
                    if ( [handler.uuid isEqual:handlerId] ) {
                        matchedHandler = handler;
                        matchedTask = mergedTask;
                        break;
                    }
                }
            }
        }
        
        if ( matchedTask == nil || matchedHandler == nil ) {
            return;
        }
        [matchedTask removeResponseHandler:matchedHandler];
        
        NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:nil];
        dispatch_main_sync_safe(^{
            if ( matchedHandler.failedBlock != nil ){
                matchedHandler.failedBlock(nil, error);
            }
        });
		
        // remove this task from both merged and queued tasks
        if (matchedTask.handlers.count == 0) {
			
			if ( [_delegate respondsToSelector:@selector(FlyImageDownloader:willCancelRequest:)] ) {
				dispatch_main_sync_safe(^{
					[_delegate FlyImageDownloader:self willCancelRequest:matchedTask.task.originalRequest];
				});
			}
			
            [matchedTask.task cancel];
            
            [self.mergedTasks removeObjectForKey:matchedTask.identifier];
            [_queuedMergedTasks removeObject:matchedTask];
        }
    });
}

- (BOOL)isActiveRequestCountBelowMaximumLimit
{
    return self.activeRequestCount < self.maxDownloadingCount;
}

- (void)startMergedTask:(FlyImageDownloaderMergedTask*)mergedTask
{
    if ([_delegate respondsToSelector:@selector(FlyImageDownloader:willSendRequest:)]) {
        dispatch_main_sync_safe(^{
			[_delegate FlyImageDownloader:self willSendRequest:mergedTask.task.originalRequest];
        });
    }

    [mergedTask.task resume];
    ++self.activeRequestCount;
}

- (void)enqueueMergedTask:(FlyImageDownloaderMergedTask*)mergedTask
{
    // default is AFImageDownloadPrioritizationLIFO
    [_queuedMergedTasks insertObject:mergedTask atIndex:0];
}

- (FlyImageDownloaderMergedTask*)dequeueMergedTask
{
    FlyImageDownloaderMergedTask* mergedTask = nil;
    mergedTask = [_queuedMergedTasks lastObject];
    [self.queuedMergedTasks removeObject:mergedTask];
    return mergedTask;
}

- (void)safelyDecrementActiveTaskCount
{
    dispatch_sync(_synchronizationQueue, ^{
        if (self.activeRequestCount > 0) {
            self.activeRequestCount -= 1;
        }
    });
}

- (void)safelyStartNextTaskIfNecessary
{
    dispatch_sync(_synchronizationQueue, ^{
        while ([self isActiveRequestCountBelowMaximumLimit] && [_queuedMergedTasks count] > 0 ) {
            FlyImageDownloaderMergedTask *mergedTask = [self dequeueMergedTask];
            [self startMergedTask:mergedTask];
        }
    });
}

@end


================================================
FILE: FlyImage/Core/FlyImageEncoder.h
================================================
//
//  FlyImageEncoder.h
//  Demo
//
//  Created by Ye Tong on 3/22/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef void (^FFlyImageEncoderDrawingBlock)(CGContextRef context, CGRect contextBounds);

/**
 *  Convert an image to bitmap format.
 */
@interface FlyImageEncoder : NSObject

/**
 *  Draw an image, and save the bitmap data into memory buffer.
 *
 *  @param size         image size
 *  @param bytes        memory buffer
 *  @param drawingBlock drawing function
 */
- (void)encodeWithImageSize:(CGSize)size
                      bytes:(void*)bytes
               drawingBlock:(FFlyImageEncoderDrawingBlock)drawingBlock;

/**
 *  Calculate buffer size with image size.
 *
 *  @param size image size
 */
+ (size_t)dataLengthWithImageSize:(CGSize)size;

@end


================================================
FILE: FlyImage/Core/FlyImageEncoder.m
================================================
//
//  FlyImageEncoder.m
//  Demo
//
//  Created by Ye Tong on 3/22/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "FlyImageEncoder.h"
#import "FlyImageUtils.h"

@implementation FlyImageEncoder

static NSInteger __bytesPerPixel = 4;
static NSInteger __bitsPerComponent = 8;
static float __alignmentSize = 64;

- (void)encodeWithImageSize:(CGSize)size
                      bytes:(void*)bytes
               drawingBlock:(FFlyImageEncoderDrawingBlock)drawingBlock
{

    CGFloat screenScale = [FlyImageUtils contentsScale];
    CGSize pixelSize = CGSizeMake(size.width * screenScale, size.height * screenScale);

    // It calculates the bytes-per-row based on the __bitsPerComponent and width arguments.
    size_t bytesPerRow = ceil((pixelSize.width * __bytesPerPixel) / __alignmentSize) * __alignmentSize;

    CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    CGContextRef context = CGBitmapContextCreate(bytes,
                                                 pixelSize.width,
                                                 pixelSize.height,
                                                 __bitsPerComponent,
                                                 bytesPerRow,
                                                 colorSpace,
                                                 bitmapInfo);
    CGColorSpaceRelease(colorSpace);

    CGContextTranslateCTM(context, 0, pixelSize.height);
    CGContextScaleCTM(context, 1, -1);

    // Call drawing block to allow client to draw into the context
    CGRect contextBounds = CGRectZero;
    contextBounds.size = pixelSize;
    CGContextClearRect(context, contextBounds);

    drawingBlock(context, contextBounds);
    CGContextRelease(context);
}

+ (size_t)dataLengthWithImageSize:(CGSize)size
{

    CGFloat screenScale = [FlyImageUtils contentsScale];
    CGSize pixelSize = CGSizeMake(size.width * screenScale, size.height * screenScale);

    size_t bytesPerRow = ceil((pixelSize.width * __bytesPerPixel) / __alignmentSize) * __alignmentSize;
    CGFloat imageLength = bytesPerRow * (NSInteger)pixelSize.height;

    int pageSize = [FlyImageUtils pageSize];
    size_t bytesToAppend = ceil(imageLength / pageSize) * pageSize;

    return bytesToAppend;
}

@end


================================================
FILE: FlyImage/Core/FlyImageIconCache.h
================================================
//
//  FlyImageIconCache.h
//  Demo
//
//  Created by Norris Tong on 4/2/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "FlyImageCacheProtocol.h"

/**
 *	Draw the icon in a background thread.
 *
 *  @param context	drawing context
 *  @param contextBounds  image size
 */
typedef void (^FlyImageCacheDrawingBlock)(CGContextRef context, CGRect contextBounds);

/**
 *	FlyImageIconCache will draw icons into one big file, 
 *  and will get great performace when try to render multiple icons in one screen.
 */
@interface FlyImageIconCache : NSObject <FlyImageCacheProtocol>

/**
 *  Add an icon into the FlyImageIconCache.
 *
 *  @param key          unique key
 *  @param size         image size
 *  @param drawingBlock
 *  @param completed    callback after add, can be nil
 */
- (void)addImageWithKey:(NSString*)key
                   size:(CGSize)size
           drawingBlock:(FlyImageCacheDrawingBlock)drawingBlock
              completed:(FlyImageCacheRetrieveBlock)completed;

/**
 *  FlyImageIconCache not support remove an icon from the cache, but you can replace an icon with the same key.
 *  But the new image must has the same size with the previous one.
 *
 *  @param key          unique key
 *  @param drawingBlock
 *  @param completed    callback after replace, can be nil
 */
- (void)replaceImageWithKey:(NSString*)key
               drawingBlock:(FlyImageCacheDrawingBlock)drawingBlock
                  completed:(FlyImageCacheRetrieveBlock)completed;

@end


================================================
FILE: FlyImage/Core/FlyImageIconCache.m
================================================
//
//  FlyImageIconCache.m
//  Demo
//
//  Created by Norris Tong on 4/2/16.
//  Copyright © 2016 NorrisTong. All rights reserved.
//

#import "FlyImageIconCache.h"
#import "FlyImageDataFileManager.h"
#import "FlyImageUtils.h"
#import "FlyImageEncoder.h"
#import "FlyImageDecoder.h"
#import "FlyImageRetrieveOperation.h"

static NSString* kFlyImageKeyVersion = @"v";
static NSString* kFlyImageKeyFile = @"f";
static NSString* kFlyImageKeyImages = @"i";
static NSString* kFlyImageKeyFilePointer = @"p";

#define kImageInfoIndexWidth 0
#define kImageInfoIndexHeight 1
#define kImageInfoIndexOffset 2
#define kImageInfoIndexLength 3
#define kImageInfoCount 4

@interface FlyImageIconCache ()
@property (nonatomic, strong) FlyImageEncoder* encoder;
@property (nonatomic, strong) FlyImageDecoder* decoder;
@property (nonatomic, strong) FlyImageDataFile* dataFile;
@property (nonatomic, strong) FlyImageDataFileManager* dataFileManager;
@end

@implementation FlyImageIconCache {
    NSRecursiveLock* _lock;
    NSString* _metaPath;

    NSMutableDictionary* _metas;
    NSMutableDictionary* _images;
    NSMutableDictionary* _addingImages;
    NSOperationQueue* _retrievingQueue;
}

+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    static FlyImageIconCache* __instance = nil;
    dispatch_once(&onceToken, ^{
		NSString *metaPath = [[FlyImageUtils directoryPath] stringByAppendingPathComponent:@"/__icons"];
        __instance = [[[self class] alloc] initWithMetaPath:metaPath];
    });

    return __instance;
}

- (instancetype)initWithMetaPath:(NSString*)metaPath
{
    if (self = [self init]) {

        _lock = [[NSRecursiveLock alloc] init];
        _addingImages = [[NSMutableDictionary alloc] init];
        _retrievingQueue = [NSOperationQueue new];
        _retrievingQueue.qualityOfService = NSQualityOfServiceUserInteractive;
        _retrievingQueue.maxConcurrentOperationCount = 6;

        _metaPath = [metaPath copy];
        NSString* folderPath = [[_metaPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"/files"];
        self.dataFileManager = [[FlyImageDataFileManager alloc] initWithFolderPath:folderPath];
        [self loadMetadata];

        _decoder = [[FlyImageDecoder alloc] init];
        _encoder = [[FlyImageEncoder alloc] init];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(onWillTerminate)
                                                     name:UIApplicationWillTerminateNotification
                                                   object:nil];
    }
    return self;
}

#pragma mark - LifeCircle
- (void)onWillTerminate
{
    // 取消内存映射
    _dataFile = nil;
    [_retrievingQueue cancelAllOperations];
}

- (void)dealloc
{
    _dataFile = nil;
    [_retrievingQueue cancelAllOperations];
}

#pragma mark - APIs
- (void)addImageWithKey:(NSString*)key
                   size:(CGSize)size
           drawingBlock:(FlyImageCacheDrawingBlock)drawingBlock
              completed:(FlyImageCacheRetrieveBlock)completed
{

    NSParameterAssert(key != nil);
    NSParameterAssert(drawingBlock != nil);

    if ([self isImageExistWithKey:key]) {
        [self asyncGetImageWithKey:key completed:completed];
        return;
    }

    size_t bytesToAppend = [FlyImageEncoder dataLengthWithImageSize:size];
    [self doAddImageWithKey:key
                       size:size
                     offset:-1
                     length:bytesToAppend
               drawingBlock:drawingBlock
                  completed:completed];
}

- (void)doAddImageWithKey:(NSString*)key
                     size:(CGSize)size
                   offset:(size_t)offset
                   length:(size_t)length
             drawingBlock:(FlyImageCacheDrawingBlock)drawingBlock
                completed:(FlyImageCacheRetrieveBlock)completed
{

    NSParameterAssert(completed != nil);

    if (_dataFile == nil) {
        if (completed != nil) {
            completed(key, nil);
        }
        return;
    }

    if (completed != nil) {
        @synchronized(_addingImages)
        {
            if ([_addingImages objectForKey:key] == nil) {
                [_addingImages setObject:[NSMutableArray arrayWithObject:completed] forKey:key];
            } else {
                NSMutableArray* blocks = [_addingImages objectForKey:key];
                [blocks addObject:completed];
                return;
            }
        }
    }

    static dispatch_queue_t __drawingQueue = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
		NSString *name = [NSString stringWithFormat:@"com.flyimage.drawicon.%@", [[NSUUID UUID] UUIDString]];
        __drawingQueue = dispatch_queue_create([name cStringUsingEncoding:NSASCIIStringEncoding], NULL);
    });

    // 使用dispatch_sync 代替 dispatch_async,防止大规模写入时出现异常
    dispatch_async(__drawingQueue, ^{
		
		size_t newOffset = offset == -1 ? (size_t)_dataFile.pointer : offset;
        if ( ![_dataFile prepareAppendDataWithOffset:newOffset length:length] ) {
            [self afterAddImage:nil key:key];
            return;
        }
        
        [_encoder encodeWithImageSize:size bytes:_dataFile.address + newOffset drawingBlock:drawingBlock];
        
        BOOL success = [_dataFile appendDataWithOffset:newOffset length:length];
        if ( !success ) {
            // TODO: consider rollback
            [self afterAddImage:nil key:key];
            return;
        }
        
        // number of dataFile, width of image, height of image, offset, length
        @synchronized (_images) {
            NSArray *imageInfo = @[ @(size.width),
                                    @(size.height),
                                    @(newOffset),
                                    @(length) ];
            
            [_images setObject:imageInfo forKey:key];
        }
        
        // callback with image
        UIImage *image = [_decoder iconImageWithBytes:_dataFile.address
                                                 offset:newOffset
                                                 length:length
											   drawSize:size];
        [self afterAddImage:image key:key];
        
        // save meta
        [self saveMetadata];
    });
}

- (void)afterAddImage:(UIImage*)image key:(NSString*)key
{
    NSArray* blocks = nil;
    @synchronized(_addingImages)
    {
        blocks = [[_addingImages objectForKey:key] copy];
        [_addingImages removeObjectForKey:key];
    }

    dispatch_main_sync_safe(^{
        for ( FlyImageCacheRetrieveBlock block in blocks) {
            block( key, image );
        }
    });
}

- (void)replaceImageWithKey:(NSString*)key
               drawingBlock:(FlyImageCacheDrawingBlock)drawingBlock
                  completed:(FlyImageCacheRetrieveBlock)completed
{

    NSParameterAssert(key != nil);
    NSParameterAssert(drawingBlock != nil);

    id imageInfo = nil;
    @synchronized(_images)
    {
        imageInfo = _images[key];
    }
    if (imageInfo == nil) {
        if (completed != nil) {
            completed(key, nil);
        }
        return;
    }

    // width of image, height of image, offset, length
    CGFloat imageWidth = [[imageInfo objectAtIndex:kImageInfoIndexWidth] floatValue];
    CGFloat imageHeight = [[imageInfo objectAtIndex:kImageInfoIndexHeight] floatValue];
    size_t imageOffset = [[imageInfo objectAtIndex:kImageInfoIndexOffset] unsignedLongValue];
    size_t imageLength = [[imageInfo objectAtIndex:kImageInfoIndexLength] unsignedLongValue];

    CGSize size = CGSizeMake(imageWidth, imageHeight);
    [self doAddImageWithKey:key
                       size:size
                     offset:imageOffset
                     length:imageLength
               drawingBlock:drawingBlock
                  completed:completed];
}

- (void)removeImageWithKey:(NSString*)key
{
    @synchronized(_images)
    {
        [_images removeObjectForKey:key];
    }
}

- (void)changeImageKey:(NSString*)oldKey newKey:(NSString*)newKey
{
    @synchronized(_images)
    {

        id imageInfo = [_images objectForKey:oldKey];
        if (imageInfo == nil) {
            return;
        }

        [_images setObject:imageInfo forKey:newKey];
        [_images removeObjectForKey:oldKey];
    }
}

- (BOOL)isImageExistWithKey:(NSString*)key
{
    @synchronized(_images)
    {
        return [_images objectForKey:key] != nil;
    }
}

- (void)asyncGetImageWithKey:(NSString*)key completed:(FlyImageCacheRetrieveBlock)completed
{
    NSParameterAssert(key != nil);
    NSParameterAssert(completed != nil);

    if (_dataFile == nil) {
        completed(key, nil);
        return;
    }

    NSArray* imageInfo;
    @synchronized(_images)
    {
        imageInfo = _images[key];
    }

    if (imageInfo == nil || [imageInfo count] < kImageInfoCount) {
        completed(key, nil);
        return;
    }

    // width of image, height of image, offset, length
    CGFloat imageWidth = [[imageInfo objectAtIndex:kImageInfoIndexWidth] floatValue];
    CGFloat imageHeight = [[imageInfo objectAtIndex:kImageInfoIndexHeight] floatValue];
    size_t imageOffset = [[imageInfo objectAtIndex:kImageInfoIndexOffset] unsignedLongValue];
    size_t imageLength = [[imageInfo objectAtIndex:kImageInfoIndexLength] unsignedLongValue];

    __weak __typeof__(self) weakSelf = self;
    FlyImageRetrieveOperation* operation = [[FlyImageRetrieveOperation alloc] initWithRetrieveBlock:^UIImage * {
		return [weakSelf.decoder iconImageWithBytes:weakSelf.dataFile.address
									 offset:imageOffset
									 length:imageLength
								   drawSize:CGSizeMake(imageWidth, imageHeight)];

    }];
    operation.name = key;
    [operation addBlock:completed];
    [_retrievingQueue addOperation:operation];
}

- (void)cancelGetImageWithKey:(NSString*)key
{
    NSParameterAssert(key != nil);

    for (FlyImageRetrieveOperation* operation in _retrievingQueue.operations) {
        if (!operation.cancelled && !operation.finished && [operation.name isEqualToString:key]) {
            [operation cancel];
            return;
        }
    }
}

- (void)purge
{
    [self removeImages];

    _dataFile = nil;
    NSString* fileName = [_metas objectForKey:kFlyImageKeyFile];
    if (fileName != nil) {
        [self.dataFileManager removeFileWithName:fileName];
        [self createDataFile:fileName];
    }

    [self saveMetadata];
}

- (void)removeImages
{
    @synchronized(_images)
    {
        [_images removeAllObjects];
    }

    [_retrievingQueue cancelAllOperations];

    @synchronized(_addingImages)
    {
        for (NSString* key in _addingImages) {
            NSArray* blocks = [_addingImages objectForKey:key];
            dispatch_main_sync_safe(^{
                for ( FlyImageCacheRetrieveBlock blo
Download .txt
gitextract_2t9t0g8x/

├── .gitignore
├── .swift-version
├── .travis.yml
├── Examples/
│   ├── FlyImageIconView/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Info.plist
│   │   └── main.m
│   ├── FlyImageView/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Cells/
│   │   │   ├── BaseTableViewCell.h
│   │   │   ├── BaseTableViewCell.m
│   │   │   ├── FlyImageIconLayerTableViewCell.h
│   │   │   ├── FlyImageIconLayerTableViewCell.m
│   │   │   ├── FlyImageIconViewTableViewCell.h
│   │   │   ├── FlyImageIconViewTableViewCell.m
│   │   │   ├── FlyImageLayerTableViewCell.h
│   │   │   ├── FlyImageLayerTableViewCell.m
│   │   │   ├── FlyImageTableViewCell.h
│   │   │   ├── FlyImageTableViewCell.m
│   │   │   ├── SDWebImageTableViewCell.h
│   │   │   ├── SDWebImageTableViewCell.m
│   │   │   ├── TriditionTableViewCell.h
│   │   │   └── TriditionTableViewCell.m
│   │   ├── Info.plist
│   │   ├── Launch Screen.storyboard
│   │   ├── ProgressImageView.h
│   │   ├── ProgressImageView.m
│   │   ├── RootViewController.h
│   │   ├── RootViewController.m
│   │   └── main.m
│   ├── FlyImageView.xcodeproj/
│   │   └── project.pbxproj
│   ├── FlyImageView.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcshareddata/
│   │       └── xcschemes/
│   │           ├── FlyImageIconView.xcscheme
│   │           ├── FlyImageView.xcscheme
│   │           ├── SingleView.xcscheme
│   │           └── WebP.xcscheme
│   ├── Podfile
│   ├── SingleView/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Info.plist
│   │   ├── SingleViewController.h
│   │   ├── SingleViewController.m
│   │   └── main.m
│   └── WebP/
│       ├── AppDelegate.h
│       ├── AppDelegate.m
│       ├── Info.plist
│       └── main.m
├── FlyImage/
│   ├── Core/
│   │   ├── FlyImageCache.h
│   │   ├── FlyImageCache.m
│   │   ├── FlyImageCacheProtocol.h
│   │   ├── FlyImageDataFile.h
│   │   ├── FlyImageDataFile.m
│   │   ├── FlyImageDataFileManager.h
│   │   ├── FlyImageDataFileManager.m
│   │   ├── FlyImageDecoder.h
│   │   ├── FlyImageDecoder.m
│   │   ├── FlyImageDownloader.h
│   │   ├── FlyImageDownloader.m
│   │   ├── FlyImageEncoder.h
│   │   ├── FlyImageEncoder.m
│   │   ├── FlyImageIconCache.h
│   │   ├── FlyImageIconCache.m
│   │   ├── FlyImageRetrieveOperation.h
│   │   ├── FlyImageRetrieveOperation.m
│   │   ├── FlyImageUtils.h
│   │   └── FlyImageUtils.m
│   ├── FlyImage.h
│   ├── Info.plist
│   └── UI/
│       ├── CALayer+FlyImageCache.h
│       ├── CALayer+FlyImageCache.m
│       ├── CALayer+FlyImageIconCache.h
│       ├── CALayer+FlyImageIconCache.m
│       ├── FlyImageCacheUIProtocol.h
│       ├── FlyImageIconCacheUIProtocol.h
│       ├── FlyImageIconRenderer.h
│       ├── FlyImageIconRenderer.m
│       ├── FlyImageRenderer.h
│       ├── FlyImageRenderer.m
│       ├── UIImageView+FlyImageCache.h
│       ├── UIImageView+FlyImageCache.m
│       ├── UIImageView+FlyImageIconCache.h
│       └── UIImageView+FlyImageIconCache.m
├── FlyImage.podspec
├── FlyImage.xcodeproj/
│   └── project.pbxproj
├── FlyImage.xcworkspace/
│   ├── contents.xcworkspacedata
│   └── xcshareddata/
│       └── xcschemes/
│           ├── FlyImage.xcscheme
│           └── FlyImageTests.xcscheme
├── FlyImageTests/
│   ├── FlyImageCacheTests.m
│   ├── FlyImageDataFileManagerTests.m
│   ├── FlyImageDataFileTests.m
│   ├── FlyImageDownloadManagerTests.m
│   ├── FlyImageIconCacheTests.m
│   └── Info.plist
├── LICENSE
├── Podfile
└── README.md
Download .txt
SYMBOL INDEX (3 symbols across 3 files)

FILE: FlyImage/Core/FlyImageDownloader.h
  type NSUUID (line 14) | typedef NSUUID FlyImageDownloadHandlerId;

FILE: FlyImage/Core/FlyImageRetrieveOperation.h
  type UIImage (line 12) | typedef UIImage* (^RetrieveOperationBlock)(void);

FILE: FlyImage/Core/FlyImageUtils.h
  type ImageContentTypeUnknown (line 10) | typedef NS_ENUM(NSInteger, ImageContentType) { ImageContentTypeUnknown,
Condensed preview — 96 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (352K chars).
[
  {
    "path": ".gitignore",
    "chars": 564,
    "preview": "# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!defau"
  },
  {
    "path": ".swift-version",
    "chars": 4,
    "preview": "2.3\n"
  },
  {
    "path": ".travis.yml",
    "chars": 1220,
    "preview": "\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 "
  },
  {
    "path": "Examples/FlyImageIconView/AppDelegate.h",
    "chars": 276,
    "preview": "//\n//  AppDelegate.h\n//  FlyImageIconView\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Augmn. All rights r"
  },
  {
    "path": "Examples/FlyImageIconView/AppDelegate.m",
    "chars": 3142,
    "preview": "//\n//  AppDelegate.m\n//  FlyImageIconView\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Augmn. All rights r"
  },
  {
    "path": "Examples/FlyImageIconView/Info.plist",
    "chars": 1619,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Examples/FlyImageIconView/main.m",
    "chars": 324,
    "preview": "//\n//  main.m\n//  FlyImageIconView\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Augmn. All rights reserved"
  },
  {
    "path": "Examples/FlyImageView/AppDelegate.h",
    "chars": 272,
    "preview": "//\n//  AppDelegate.h\n//  FlyImageView\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 Augmn. All rights reser"
  },
  {
    "path": "Examples/FlyImageView/AppDelegate.m",
    "chars": 3203,
    "preview": "//\n//  AppDelegate.m\n//  FlyImageView\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 Augmn. All rights reser"
  },
  {
    "path": "Examples/FlyImageView/Cells/BaseTableViewCell.h",
    "chars": 363,
    "preview": "//\n//  BaseTableViewCell.h\n//  Demo\n//\n//  Created by Norris Tong on 4/15/16.\n//  Copyright © 2016 NorrisTong. All right"
  },
  {
    "path": "Examples/FlyImageView/Cells/BaseTableViewCell.m",
    "chars": 1385,
    "preview": "//\n//  BaseTableViewCell.m\n//  Demo\n//\n//  Created by Norris Tong on 4/15/16.\n//  Copyright © 2016 NorrisTong. All right"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageIconLayerTableViewCell.h",
    "chars": 247,
    "preview": "//\n//  FlyImageIconLayerTableViewCell.h\n//  FlyImageView\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Augm"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageIconLayerTableViewCell.m",
    "chars": 632,
    "preview": "//\n//  FlyImageIconLayerTableViewCell.m\n//  FlyImageView\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Augm"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageIconViewTableViewCell.h",
    "chars": 244,
    "preview": "//\n//  FlyImageIconViewTableViewCell.h\n//  FlyImageView\n//\n//  Created by Ye Tong on 5/3/16.\n//  Copyright © 2016 Augmn."
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageIconViewTableViewCell.m",
    "chars": 624,
    "preview": "//\n//  FlyImageIconViewTableViewCell.m\n//  FlyImageView\n//\n//  Created by Ye Tong on 5/3/16.\n//  Copyright © 2016 Augmn."
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageLayerTableViewCell.h",
    "chars": 236,
    "preview": "//\n//  FlyImageLayerTableViewCell.h\n//  Demo\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 NorrisTong. All "
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageLayerTableViewCell.m",
    "chars": 612,
    "preview": "//\n//  FlyImageLayerTableViewCell.m\n//  Demo\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 NorrisTong. All "
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageTableViewCell.h",
    "chars": 230,
    "preview": "//\n//  FlyImageTableViewCell.h\n//  Demo\n//\n//  Created by Norris Tong on 4/14/16.\n//  Copyright © 2016 NorrisTong. All r"
  },
  {
    "path": "Examples/FlyImageView/Cells/FlyImageTableViewCell.m",
    "chars": 646,
    "preview": "//\n//  FlyImageTableViewCell.m\n//  Demo\n//\n//  Created by Norris Tong on 4/14/16.\n//  Copyright © 2016 NorrisTong. All r"
  },
  {
    "path": "Examples/FlyImageView/Cells/SDWebImageTableViewCell.h",
    "chars": 230,
    "preview": "//\n//  SDWebImageTableViewCell.h\n//  Demo\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 NorrisTong. All rig"
  },
  {
    "path": "Examples/FlyImageView/Cells/SDWebImageTableViewCell.m",
    "chars": 627,
    "preview": "//\n//  SDWebImageTableViewCell.m\n//  Demo\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 NorrisTong. All rig"
  },
  {
    "path": "Examples/FlyImageView/Cells/TriditionTableViewCell.h",
    "chars": 232,
    "preview": "//\n//  TriditionTableViewCell.h\n//  Demo\n//\n//  Created by Norris Tong on 4/14/16.\n//  Copyright © 2016 NorrisTong. All "
  },
  {
    "path": "Examples/FlyImageView/Cells/TriditionTableViewCell.m",
    "chars": 2637,
    "preview": "//\n//  TriditionTableViewCell.m\n//  Demo\n//\n//  Created by Norris Tong on 4/14/16.\n//  Copyright © 2016 NorrisTong. All "
  },
  {
    "path": "Examples/FlyImageView/Info.plist",
    "chars": 1508,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Examples/FlyImageView/Launch Screen.storyboard",
    "chars": 1665,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "Examples/FlyImageView/ProgressImageView.h",
    "chars": 209,
    "preview": "//\n//  ProgressImageView.h\n//  FlyImageView\n//\n//  Created by Ye Tong on 8/12/16.\n//  Copyright © 2016 Augmn. All rights"
  },
  {
    "path": "Examples/FlyImageView/ProgressImageView.m",
    "chars": 768,
    "preview": "//\n//  ProgressImageView.m\n//  FlyImageView\n//\n//  Created by Ye Tong on 8/12/16.\n//  Copyright © 2016 Augmn. All rights"
  },
  {
    "path": "Examples/FlyImageView/RootViewController.h",
    "chars": 464,
    "preview": "//\n//  RootViewController.h\n//  Demo\n//\n//  Created by Ye Tong on 3/24/16.\n//  Copyright © 2016 NorrisTong. All rights r"
  },
  {
    "path": "Examples/FlyImageView/RootViewController.m",
    "chars": 4642,
    "preview": "//\n//  RootViewController.m\n//  Demo\n//\n//  Created by Ye Tong on 3/24/16.\n//  Copyright © 2016 NorrisTong. All rights r"
  },
  {
    "path": "Examples/FlyImageView/main.m",
    "chars": 320,
    "preview": "//\n//  main.m\n//  FlyImageView\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 Augmn. All rights reserved.\n//"
  },
  {
    "path": "Examples/FlyImageView.xcodeproj/project.pbxproj",
    "chars": 47692,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "Examples/FlyImageView.xcworkspace/contents.xcworkspacedata",
    "chars": 230,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:FlyImageView.x"
  },
  {
    "path": "Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/FlyImageIconView.xcscheme",
    "chars": 3395,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/FlyImageView.xcscheme",
    "chars": 3363,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/SingleView.xcscheme",
    "chars": 3347,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Examples/FlyImageView.xcworkspace/xcshareddata/xcschemes/WebP.xcscheme",
    "chars": 3299,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Examples/Podfile",
    "chars": 480,
    "preview": "platform :ios, '8.0'\n\n# ignore all warnings from all pods\ninhibit_all_warnings!\n\ntarget 'FlyImageView' do\n\tpod 'SDWebIma"
  },
  {
    "path": "Examples/SingleView/AppDelegate.h",
    "chars": 269,
    "preview": "//\n//  AppDelegate.h\n//  SingleView\n//\n//  Created by Ye Tong on 5/9/16.\n//  Copyright © 2016 Augmn. All rights reserved"
  },
  {
    "path": "Examples/SingleView/AppDelegate.m",
    "chars": 2333,
    "preview": "//\n//  AppDelegate.m\n//  SingleView\n//\n//  Created by Ye Tong on 5/9/16.\n//  Copyright © 2016 Augmn. All rights reserved"
  },
  {
    "path": "Examples/SingleView/Info.plist",
    "chars": 1509,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Examples/SingleView/SingleViewController.h",
    "chars": 213,
    "preview": "//\n//  ViewController.h\n//  SingleView\n//\n//  Created by Ye Tong on 5/9/16.\n//  Copyright © 2016 Augmn. All rights reser"
  },
  {
    "path": "Examples/SingleView/SingleViewController.m",
    "chars": 4118,
    "preview": "//\n//  SingleViewController.m\n//  SingleView\n//\n//  Created by Ye Tong on 5/9/16.\n//  Copyright © 2016 Augmn. All rights"
  },
  {
    "path": "Examples/SingleView/main.m",
    "chars": 317,
    "preview": "//\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#"
  },
  {
    "path": "Examples/WebP/AppDelegate.h",
    "chars": 263,
    "preview": "//\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"
  },
  {
    "path": "Examples/WebP/AppDelegate.m",
    "chars": 2920,
    "preview": "//\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"
  },
  {
    "path": "Examples/WebP/Info.plist",
    "chars": 1509,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Examples/WebP/main.m",
    "chars": 311,
    "preview": "//\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"
  },
  {
    "path": "FlyImage/Core/FlyImageCache.h",
    "chars": 2353,
    "preview": "//\n//  FlyImageCache.h\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All rights reserv"
  },
  {
    "path": "FlyImage/Core/FlyImageCache.m",
    "chars": 18952,
    "preview": "//\n//  FlyImageCache.m\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All rights reserv"
  },
  {
    "path": "FlyImage/Core/FlyImageCacheProtocol.h",
    "chars": 1420,
    "preview": "//\n//  FlyImageCacheProtocol.h\n//  Demo\n//\n//  Created by Norris Tong on 4/2/16.\n//  Copyright © 2016 NorrisTong. All ri"
  },
  {
    "path": "FlyImage/Core/FlyImageDataFile.h",
    "chars": 1349,
    "preview": "//\n//  FlyImageDataFile.h\n//  Demo\n//\n//  Created by Ye Tong on 3/18/16.\n//  Copyright © 2016 NorrisTong. All rights res"
  },
  {
    "path": "FlyImage/Core/FlyImageDataFile.m",
    "chars": 3243,
    "preview": "//\n//  FlyImageDataFile.m\n//  Demo\n//\n//  Created by Ye Tong on 3/18/16.\n//  Copyright © 2016 NorrisTong. All rights res"
  },
  {
    "path": "FlyImage/Core/FlyImageDataFileManager.h",
    "chars": 1849,
    "preview": "//\n//  FlyImageDataFileManager.h\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rig"
  },
  {
    "path": "FlyImage/Core/FlyImageDataFileManager.m",
    "chars": 10333,
    "preview": "//\n//  FlyImageDataFileManager.m\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rig"
  },
  {
    "path": "FlyImage/Core/FlyImageDecoder.h",
    "chars": 1476,
    "preview": "//\n//  FlyImageDecoder.h\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights rese"
  },
  {
    "path": "FlyImage/Core/FlyImageDecoder.m",
    "chars": 11257,
    "preview": "//\n//  FlyImageDecoder.m\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights rese"
  },
  {
    "path": "FlyImage/Core/FlyImageDownloader.h",
    "chars": 2570,
    "preview": "//\n//  FlyImageDownloader.h\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights r"
  },
  {
    "path": "FlyImage/Core/FlyImageDownloader.m",
    "chars": 15872,
    "preview": "//\n//  FlyImageDownloader.m\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights r"
  },
  {
    "path": "FlyImage/Core/FlyImageEncoder.h",
    "chars": 811,
    "preview": "//\n//  FlyImageEncoder.h\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights rese"
  },
  {
    "path": "FlyImage/Core/FlyImageEncoder.m",
    "chars": 2350,
    "preview": "//\n//  FlyImageEncoder.m\n//  Demo\n//\n//  Created by Ye Tong on 3/22/16.\n//  Copyright © 2016 NorrisTong. All rights rese"
  },
  {
    "path": "FlyImage/Core/FlyImageIconCache.h",
    "chars": 1520,
    "preview": "//\n//  FlyImageIconCache.h\n//  Demo\n//\n//  Created by Norris Tong on 4/2/16.\n//  Copyright © 2016 NorrisTong. All rights"
  },
  {
    "path": "FlyImage/Core/FlyImageIconCache.m",
    "chars": 13777,
    "preview": "//\n//  FlyImageIconCache.m\n//  Demo\n//\n//  Created by Norris Tong on 4/2/16.\n//  Copyright © 2016 NorrisTong. All rights"
  },
  {
    "path": "FlyImage/Core/FlyImageRetrieveOperation.h",
    "chars": 782,
    "preview": "//\n//  FlyImageRetrieveOperation.h\n//  FlyImage\n//\n//  Created by Ye Tong on 8/11/16.\n//  Copyright © 2016 Ye Tong. All "
  },
  {
    "path": "FlyImage/Core/FlyImageRetrieveOperation.m",
    "chars": 1053,
    "preview": "//\n//  FlyImageRetrieveOperation.m\n//  FlyImage\n//\n//  Created by Ye Tong on 8/11/16.\n//  Copyright © 2016 Ye Tong. All "
  },
  {
    "path": "FlyImage/Core/FlyImageUtils.h",
    "chars": 2084,
    "preview": "//\n//  FlyImageUtils.h\n//  Demo\n//\n//  Created by Ye Tong on 3/18/16.\n//  Copyright © 2016 NorrisTong. All rights reserv"
  },
  {
    "path": "FlyImage/Core/FlyImageUtils.m",
    "chars": 6779,
    "preview": "//\n//  FlyImageUtils.m\n//  Demo\n//\n//  Created by Ye Tong on 3/18/16.\n//  Copyright © 2016 NorrisTong. All rights reserv"
  },
  {
    "path": "FlyImage/FlyImage.h",
    "chars": 786,
    "preview": "//\n//  FlyImage.h\n//  FlyImage\n//\n//  Created by Ye Tong on 4/18/16.\n//  Copyright © 2016 Ye Tong. All rights reserved.\n"
  },
  {
    "path": "FlyImage/Info.plist",
    "chars": 796,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "FlyImage/UI/CALayer+FlyImageCache.h",
    "chars": 256,
    "preview": "//\n//  FlyImageLayer.h\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All rights reserv"
  },
  {
    "path": "FlyImage/UI/CALayer+FlyImageCache.m",
    "chars": 2549,
    "preview": "//\n//  CALayer+FlyImageCache.m\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All right"
  },
  {
    "path": "FlyImage/UI/CALayer+FlyImageIconCache.h",
    "chars": 281,
    "preview": "//\n//  CALayer+FlyImageIconCache.h\n//  FlyImage\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Ye Tong. All "
  },
  {
    "path": "FlyImage/UI/CALayer+FlyImageIconCache.m",
    "chars": 2860,
    "preview": "//\n//  CALayer+FlyImageIconCache.m\n//  FlyImage\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Ye Tong. All "
  },
  {
    "path": "FlyImage/UI/FlyImageCacheUIProtocol.h",
    "chars": 921,
    "preview": "//\n//  FlyImageCacheUIProtocol.h\n//  FlyImage\n//\n//  Created by Ye Tong on 8/9/16.\n//  Copyright © 2016 Ye Tong. All rig"
  },
  {
    "path": "FlyImage/UI/FlyImageIconCacheUIProtocol.h",
    "chars": 829,
    "preview": "//\n//  FlyImageIconCacheUIProtocol.h\n//  FlyImage\n//\n//  Created by Ye Tong on 8/9/16.\n//  Copyright © 2016 Ye Tong. All"
  },
  {
    "path": "FlyImage/UI/FlyImageIconRenderer.h",
    "chars": 916,
    "preview": "//\n//  FlyImageIconRenderer.h\n//  FlyImage\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Ye Tong. All right"
  },
  {
    "path": "FlyImage/UI/FlyImageIconRenderer.m",
    "chars": 4424,
    "preview": "//\n//  FlyImageIconRenderer.m\n//  FlyImage\n//\n//  Created by Ye Tong on 4/27/16.\n//  Copyright © 2016 Ye Tong. All right"
  },
  {
    "path": "FlyImage/UI/FlyImageRenderer.h",
    "chars": 1100,
    "preview": "//\n//  FlyImageRenderer.h\n//  Demo\n//\n//  Created by Norris Tong on 4/11/16.\n//  Copyright © 2016 NorrisTong. All rights"
  },
  {
    "path": "FlyImage/UI/FlyImageRenderer.m",
    "chars": 9656,
    "preview": "//\n//  FlyImageRenderer.m\n//  Demo\n//\n//  Created by Norris Tong on 4/11/16.\n//  Copyright © 2016 NorrisTong. All rights"
  },
  {
    "path": "FlyImage/UI/UIImageView+FlyImageCache.h",
    "chars": 272,
    "preview": "//\n//  UIImageView+FlyImageCache.h\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All r"
  },
  {
    "path": "FlyImage/UI/UIImageView+FlyImageCache.m",
    "chars": 2271,
    "preview": "//\n//  UIImageView+FlyImageCache.m\n//  Demo\n//\n//  Created by Ye Tong on 3/17/16.\n//  Copyright © 2016 NorrisTong. All r"
  },
  {
    "path": "FlyImage/UI/UIImageView+FlyImageIconCache.h",
    "chars": 288,
    "preview": "//\n//  UIImageView+FlyImageIconCache.h\n//  FlyImage\n//\n//  Created by Ye Tong on 5/3/16.\n//  Copyright © 2016 Ye Tong. A"
  },
  {
    "path": "FlyImage/UI/UIImageView+FlyImageIconCache.m",
    "chars": 2613,
    "preview": "//\n//  UIImageView+FlyImageIconCache.m\n//  FlyImage\n//\n//  Created by Ye Tong on 5/3/16.\n//  Copyright © 2016 Ye Tong. A"
  },
  {
    "path": "FlyImage.podspec",
    "chars": 1749,
    "preview": "Pod::Spec.new do |s|\n  s.name         = \"FlyImage\"\n  s.version      = \"1.1\"\n  s.summary      = \"Download, cache, render "
  },
  {
    "path": "FlyImage.xcodeproj/project.pbxproj",
    "chars": 37280,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "FlyImage.xcworkspace/contents.xcworkspacedata",
    "chars": 226,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:FlyImage.xcode"
  },
  {
    "path": "FlyImage.xcworkspace/xcshareddata/xcschemes/FlyImage.xcscheme",
    "chars": 3658,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "FlyImage.xcworkspace/xcshareddata/xcschemes/FlyImageTests.xcscheme",
    "chars": 1922,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0830\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "FlyImageTests/FlyImageCacheTests.m",
    "chars": 7402,
    "preview": "//\n//  FlyImageCacheTests.m\n//  Demo\n//\n//  Created by Norris Tong on 4/3/16.\n//  Copyright © 2016 NorrisTong. All right"
  },
  {
    "path": "FlyImageTests/FlyImageDataFileManagerTests.m",
    "chars": 4786,
    "preview": "//\n//  FlyImageDataFileManagerTests.m\n//  Demo\n//\n//  Created by Norris Tong on 4/2/16.\n//  Copyright © 2016 NorrisTong."
  },
  {
    "path": "FlyImageTests/FlyImageDataFileTests.m",
    "chars": 5261,
    "preview": "//\n//  FlyImageDataFileTests.m\n//  Demo\n//\n//  Created by Norris Tong on 16/3/20.\n//  Copyright © 2016年 NorrisTong. All "
  },
  {
    "path": "FlyImageTests/FlyImageDownloadManagerTests.m",
    "chars": 8199,
    "preview": "//\n//  FlyImageDownloaderTests.m\n//  Demo\n//\n//  Created by Norris Tong on 4/4/16.\n//  Copyright © 2016 NorrisTong. All "
  },
  {
    "path": "FlyImageTests/FlyImageIconCacheTests.m",
    "chars": 11591,
    "preview": "//\n//  FlyImageIconCacheTests.m\n//  Demo\n//\n//  Created by Norris Tong on 4/3/16.\n//  Copyright © 2016 NorrisTong. All r"
  },
  {
    "path": "FlyImageTests/Info.plist",
    "chars": 733,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "LICENSE",
    "chars": 1082,
    "preview": "Copyright (c) 2016 Olivier Poitrey rs@dailymotion.com\n \nPermission is hereby granted, free of charge, to any person obta"
  },
  {
    "path": "Podfile",
    "chars": 159,
    "preview": "platform :ios, '8.0'\n\n# ignore all warnings from all pods\ninhibit_all_warnings!\n\ntarget \"FlyImage\" do\n  pod 'AFNetworkin"
  },
  {
    "path": "README.md",
    "chars": 4001,
    "preview": "![FlyImage Logo](Docs/logo.png) FlyImage\n=========\n[![Build Status](https://travis-ci.org/northwind/FlyImage.svg?branch="
  }
]

About this extraction

This page contains the full source code of the northwind/FlyImage GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 96 files (315.8 KB), approximately 87.6k tokens, and a symbol index with 3 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!