master efe1af47461b cached
84 files
374.8 KB
102.6k tokens
6 symbols
1 requests
Download .txt
Showing preview only (414K chars total). Download the full file or copy to clipboard to get everything.
Repository: netyouli/WHC_FileDownloadDemo
Branch: master
Commit: efe1af47461b
Files: 84
Total size: 374.8 KB

Directory structure:
gitextract_dw57sunh/

├── LICENSE
├── README.md
├── WHCNetWorkKit/
│   ├── Info.plist
│   ├── NSURLConnection/
│   │   ├── WHC_BaseOperation.h
│   │   ├── WHC_BaseOperation.m
│   │   ├── WHC_DownloadOperation.h
│   │   ├── WHC_DownloadOperation.m
│   │   ├── WHC_HttpManager.h
│   │   ├── WHC_HttpManager.m
│   │   ├── WHC_HttpOperation.h
│   │   └── WHC_HttpOperation.m
│   ├── NSURLSession/
│   │   ├── WHC_DownloadSessionTask.h
│   │   ├── WHC_DownloadSessionTask.m
│   │   ├── WHC_SessionDownloadManager.h
│   │   └── WHC_SessionDownloadManager.m
│   ├── Reachability/
│   │   ├── Reachability.h
│   │   └── Reachability.m
│   ├── UIKit+WHCNetWorkKit/
│   │   ├── UIButton+WHC_HttpButton.h
│   │   ├── UIButton+WHC_HttpButton.m
│   │   ├── UIImageView+WHC_HttpImageView.h
│   │   ├── UIImageView+WHC_HttpImageView.m
│   │   ├── WHC_ImageCache.h
│   │   └── WHC_ImageCache.m
│   ├── UtilKit+WHCNetWorkKit/
│   │   ├── WHC_DataModel.h
│   │   ├── WHC_DataModel.m
│   │   ├── WHC_Json.h
│   │   ├── WHC_Json.m
│   │   ├── WHC_XMLParser.h
│   │   ├── WHC_XMLParser.m
│   │   ├── WHC_Xml.h
│   │   └── WHC_Xml.m
│   └── WHCNetWorkKit.h
├── WHCNetWorkKit Example/
│   ├── AppDelegate.h
│   ├── AppDelegate.m
│   ├── Assets.xcassets/
│   │   └── AppIcon.appiconset/
│   │       └── Contents.json
│   ├── Base.lproj/
│   │   └── LaunchScreen.storyboard
│   ├── Info.plist
│   ├── UI/
│   │   ├── WHC_FillScreenPlayerVC.h
│   │   ├── WHC_FillScreenPlayerVC.m
│   │   ├── WHC_OffLineVideoCell.xib
│   │   ├── WHC_OffLineVideoVC.h
│   │   ├── WHC_OffLineVideoVC.m
│   │   └── WHC_OffLineVideoVC.xib
│   ├── UIUnitCore/
│   │   ├── UIScrollView+WHC_PullRefresh.h
│   │   ├── UIScrollView+WHC_PullRefresh.m
│   │   ├── UIView+WHC_Loading.h
│   │   ├── UIView+WHC_Loading.m
│   │   ├── UIView+WHC_Toast.h
│   │   ├── UIView+WHC_Toast.m
│   │   ├── UIView+WHC_ViewProperty.h
│   │   └── UIView+WHC_ViewProperty.m
│   ├── ViewController.h
│   ├── ViewController.m
│   ├── ViewController.xib
│   ├── WHC_DownloadObject.h
│   ├── WHC_DownloadObject.m
│   └── main.m
├── WHCNetWorkKit Example.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcuserdata/
│   │       └── wuhaichao.xcuserdatad/
│   │           └── UserInterfaceState.xcuserstate
│   └── xcuserdata/
│       ├── WHC.xcuserdatad/
│       │   └── xcschemes/
│       │       ├── WHCNetWorkKit Example.xcscheme
│       │       └── xcschememanagement.plist
│       └── wuhaichao.xcuserdatad/
│           └── xcschemes/
│               ├── WHCNetWorkKit Example.xcscheme
│               └── xcschememanagement.plist
├── WHCNetWorkKit ExampleTests/
│   ├── Info.plist
│   └── WHCNetWorkKit_ExampleTests.m
├── WHCNetWorkKit ExampleUITests/
│   ├── Info.plist
│   └── WHCNetWorkKit_ExampleUITests.m
├── WHCNetWorkKit.podspec
├── WHCNetWorkKit.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcuserdata/
│   │       └── wuhaichao.xcuserdatad/
│   │           └── UserInterfaceState.xcuserstate
│   └── xcuserdata/
│       ├── WHC.xcuserdatad/
│       │   └── xcschemes/
│       │       ├── WHCNetWorkKit.xcscheme
│       │       └── xcschememanagement.plist
│       └── wuhaichao.xcuserdatad/
│           └── xcschemes/
│               ├── WHCNetWorkKit.xcscheme
│               └── xcschememanagement.plist
├── WHCNetWorkKit.xcworkspace/
│   ├── contents.xcworkspacedata
│   └── xcuserdata/
│       ├── WHC.xcuserdatad/
│       │   ├── UserInterfaceState.xcuserstate
│       │   └── xcdebugger/
│       │       └── Breakpoints_v2.xcbkptlist
│       └── wuhaichao.xcuserdatad/
│           ├── UserInterfaceState.xcuserstate
│           ├── xcdebugger/
│           │   └── Breakpoints_v2.xcbkptlist
│           └── xcschemes/
│               └── xcschememanagement.plist
└── WHCNetWorkKitTests/
    ├── Info.plist
    └── WHCNetWorkKitTests.m

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

================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2015 吴海超

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# WHCNetWorkKit 网络操作开源库

###咨询QQ:712641411     
###开发作者:吴海超

###目前封装最好使用最简单的文件下载(支持后台下载)iOS网络开源库 该版本进行了增强包括如下功能:
###GET/POST网络请求/多文件上传/后台文件下载/网络状态监控/UIButton,UIImageView 设置网络图片等功能模块。
###封装网络常用工具类json/xml 转模型类对象 json/xml 解析
###文件下载模块代理可以自由替换代理或者回调块具体详情请参看自带demo

###安装集成方式
```ruby
platform :ios, '7.0'
pod "WHCNetWorkKit", "~> 0.0.3"
```

##运行效果
![](https://github.com/netyouli/WHCNetWorkKit/blob/master/show.gif)

###网络状态监听 Use Example
```objective-c

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
    [[WHC_HttpManager shared] registerNetworkStatusMoniterEvent];
    return YES;
}

/// 在其他地方可以这样[WHC_HttpManager shared].networkStatus获取当前网络状态
   (该网络库每次进行请求都自动处理了网络状态不需要用户进行判断)
switch ([WHC_HttpManager shared].networkStatus) {
    case NotReachable:{
        [[[UIAlertView alloc]initWithTitle:nil
        message:@"当前网络不可用请检查网络设置"
        delegate:nil cancelButtonTitle:@"确定"
        otherButtonTitles:nil, nil] show];
    }
    break;
    case ReachableViaWiFi:
        NSLog(@"====当前网络状态为Wifi=======");
    break;
    case ReachableViaWWAN:
        NSLog(@"====当前网络状态为3G=======");
    break;
}

```


###GET请求 Use Example
```objective-c
[[WHC_HttpManager shared] get:@"http://www.baidu.com/"
                  didFinished:^(WHC_BaseOperation *operation,
                                                NSData *data,
                                                NSError *error,
                                                BOOL isSuccess) {
     //处理data数据
}];


```


###POST 请求 Use Example

```objective-c

[[WHC_HttpManager shared] post:@"http://www.baidu.com"
                         param:@"whc"
                   didFinished:^(WHC_BaseOperation *operation,
                                                 NSData *data, 
                                               NSError *error,
                                               BOOL isSuccess) {
        //处理data数据
}];
```

###多文件上传 Use Example
```objective-c
//上传5个文件
for (int i = 0; i < 5; i++) {
    UIImage * image = [UIImage imageNamed:@"whc"];
    NSData * imageData = UIImageJPEGRepresentation(image, 0.5);
    [[WHC_HttpManager shared] addUploadFileData:imageData withFileName:[NSString stringWithFormat:@"image%d",i] mimeType:@"image/jpep" forKey:@"file"];
    //最后一个参数key必须和服务端对应
}
[[WHC_HttpManager shared] upload:@"http://www.baidu.com"
                           param:@"param" didFinished:^(WHC_BaseOperation *operation,
                                                                            NSData *data,
                                                                            NSError *error,
                                                                            BOOL isSuccess) {
        //处理上传结果数据
}];

```

###普通文件下载 Use Example
```objective-c
WHC_DownloadOperation * downloadTask = nil;
downloadTask = [[WHC_HttpManager shared] download:kWHC_DefaultDownloadUrl
                                         savePath:[WHC_DownloadObject videoDirectory]
                                     saveFileName:fileName
                                         response:^(WHC_BaseOperation *operation, NSError *error, BOOL isOK) {
                                        if (isOK) {
                                            [weakSelf.view toast:@"已经添加到下载队列"];
                                            WHC_DownloadOperation * downloadOperation = (WHC_DownloadOperation*)operation;
                                            WHC_DownloadObject * downloadObject = [WHC_DownloadObject new];
                                            downloadObject.fileName = downloadOperation.saveFileName;
                                            downloadObject.downloadPath = downloadOperation.strUrl;
                                            downloadObject.downloadState = WHCDownloading;
                                            downloadObject.currentDownloadLenght = downloadOperation.recvDataLenght;
                                            downloadObject.totalLenght = downloadOperation.fileTotalLenght;
                                            [downloadObject writeDiskCache];
                                        }else {
                                            [weakSelf.view toast:error.userInfo[NSLocalizedDescriptionKey]];
                                        }
                                    } process:^(WHC_BaseOperation *operation, uint64_t recvLength, uint64_t totalLength, NSString *speed) {
                                            NSLog(@"recvLength = %llu totalLength = %llu speed = %@",recvLength , totalLength , speed);
                                    } didFinished:^(WHC_BaseOperation *operation, NSData *data, NSError *error, BOOL isSuccess) {
                                        if (isSuccess) {
                                            [weakSelf.view toast:@"下载成功"];
                                            [weakSelf saveDownloadStateOperation:(WHC_DownloadOperation *)operation];
                                        }else {
                                            [weakSelf.view toast:error.userInfo[NSLocalizedDescriptionKey]];
                                        if (error != nil &&
                                            error.code == WHCCancelDownloadError) {
                                            [weakSelf saveDownloadStateOperation:(WHC_DownloadOperation *)operation];
                                        }
                                    }
}];

```

###后台文件下载 Use Example
```objective-c
[[WHC_SessionDownloadManager shared] setBundleIdentifier:@"com.WHC.WHCNetWorkKit.backgroundsession"];
WHC_DownloadSessionTask * downloadTask = [[WHC_SessionDownloadManager shared]
                                                                    download:kWHC_DefaultDownloadUrl
                                                                    savePath:[WHC_DownloadObject videoDirectory]
                                                                saveFileName:fileName
                                                                    response:^(WHC_BaseOperation *operation, NSError *error, BOOL isOK) {
                                                                    [weakSelf.view toast:@"已经添加到下载队列"];
                                                                    WHC_DownloadOperation * downloadOperation = (WHC_DownloadOperation*)operation;
                                                                    WHC_DownloadObject * downloadObject = [WHC_DownloadObject new];
                                                                    downloadObject.fileName = downloadOperation.saveFileName;
                                                                    downloadObject.downloadPath = downloadOperation.strUrl;
                                                                    downloadObject.downloadState = WHCDownloading;
                                                                    downloadObject.currentDownloadLenght = downloadOperation.recvDataLenght;
                                                                    downloadObject.totalLenght = downloadOperation.fileTotalLenght;
                                                                    [downloadObject writeDiskCache];
                                                                } process:^(WHC_BaseOperation *operation, uint64_t recvLength, uint64_t totalLength, NSString *speed) {
                                                                    NSLog(@"recvLength = %llu , totalLength = %llu , speed = %@",recvLength , totalLength , speed);
                                                                } didFinished:^(WHC_BaseOperation *operation, NSData *data, NSError *error, BOOL isSuccess) {
                                                                    if (isSuccess) {
                                                                        [weakSelf.view toast:@"下载成功"];
                                                                        [weakSelf saveDownloadStateOperation:(WHC_DownloadOperation *)operation];
                                                                    }else {
                                                                        [weakSelf.view toast:error.userInfo[NSLocalizedDescriptionKey]];
                                                                        if (error != nil &&
                                                                            error.code == WHCCancelDownloadError) {
                                                                            [weakSelf saveDownloadStateOperation:(WHC_DownloadOperation *)operation];
                                                                        }
                                                                    }
}];
```

###UIButton设置网络图片  Use Example
```objective-c
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button whc_setBackgroundImageWithURL:@"http://www.baidu.com" forState:UIControlStateNormal];
[button whc_setBackgroundImageWithURL:@"http://www.baidu.com" forState:UIControlStateNormal placeholderImage:[UIImage imageNamed:@"whc"]];
[button whc_setImageWithUrl:@"http://www.baidu.com" forState:UIControlStateNormal];
[button whc_setImageWithUrl:@"http://www.baidu.com" forState:UIControlStateNormal placeholderImage:[UIImage imageNamed:@"whc"]];
```

####UIImageView设置网络图片  Use Example
```objective-c
UIImageView * imageView = [UIImageView new];
[imageView whc_setImageWithUrl:@"http://www.baidu.com"];
[imageView whc_setImageWithUrl:@"http://www.baidu.com" placeholderImage:[UIImage imageNamed:@"whc"]];
```

###Json 转模型类  Use Example
###支持无限json嵌套解析转换 (开源MAC工具WHC_DataModelFactory 自动把json或者xml字符串生成模型类.m和.h文件
###省去手工创建模型类繁琐避免出错 开源链接:https://github.com/netyouli/WHC_DataModelFactory)
```objective-c
typedef enum {
    SexMale,
    SexFemale
} sex;

@interface User : NSObject
@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *icon;
@property (strong, nonatomic) NSNumber * age;
@property (strong, nonatomic) NSNumber * height;
@property (strong, nonatomic) NSNumber *money;
@property (strong, nonatomic) sex  *sex;
@end

/***********************************************/


NSDictionary *dict = @{
@"name" : @"Jack",
@"icon" : @"lufy.png",
@"age" : @20,
@"height" : @"1.55",
@"money" : @100.9,
@"sex" : @(SexFemale)
};
// JSON -> User
User * user = [WHC_DataModel dataModelWithDictionary:dict className:[User class]];

NSLog(@"name=%@, icon=%@, age=%@, height=%@, money=%@, sex=%@",
user.name, user.icon, user.age, user.height, user.money, user.sex);
// name=Jack, icon=lufy.png, age=20, height=1.550000, money=100.9, sex=1
```

###XML 转模型类 Use Example
```objective-c
NSString  * xml = @"<?xml version=\"1.0\" encoding=\"utf-8\"?>\
<ebMobileStartupInqRq >\
<REQHDR>\
<TrnNum>INHB2015042900000001</TrnNum>\
<TrnCode>1957747793</TrnCode>\
</REQHDR>\
<REQBDY>\
<OS>iPhone</OS>\
<App>CC</App>\
<IconVersion></IconVersion>\
</REQBDY>\
</ebMobileStartupInqRq>";

@interface REQBDY :NSObject
@property (nonatomic , copy) NSString              * OS;
@property (nonatomic , copy) NSString              * App;
@property (nonatomic , copy) NSString              * IconVersion;

@end

@interface REQHDR :NSObject
@property (nonatomic , copy) NSString              * TrnCode;
@property (nonatomic , copy) NSString              * TrnNum;

@end

@interface ebMobileStartupInqRq :NSObject
@property (nonatomic , strong) REQBDY              * REQBDY;
@property (nonatomic , strong) REQHDR              * REQHDR;

@end

@interface User :NSObject
@property (nonatomic , strong) ebMobileStartupInqRq              * ebMobileStartupInqRq;

@end


///上面模型类生成是用开源MAC工具WHC_DataModelFactory 自动生成 
///开源地址:https://github.com/netyouli/WHC_DataModelFactory
///首先用开源WHC_XMLParser 把xml转换为字典对象 然后用WHC_DataModel转模型对象
NSDictionary * xmlDictionary = [WHC_XMLParser dictionaryForXMLString:xml];
User * user = [WHC_DataModel dataModelWithDictionary:xmlDictionary
                                           className:[User class]];
NSLog(@"%@",ebMobile);

```
### 字典转换Json字符串 Use Example
```objective-c
NSDictionary * jsonDictionary = @{@"whc":@"吴海超"};
NSString * json = [WHC_Json jsonWithDictionary:jsonDictionary];
```

### Json字符串/JsonData转NSDictionary对象 Use Example
```objective-c
NSString * json = @"{"whc":"吴海超"}";
NSDictionary * jsonDictionary = [WHC_Json dictionaryWithJson:json];
jsonDictionary = [WHC_Json dictionaryWithJsonData:[json
                dataUsingEncoding:NSUTF8StringEncoding]];
```

### Json字符串/JsonData 转NSArray对象 Use Example
```objective-c
NSString * json = @""WHC":{{"android":"资深android开发者"} , {"iOS":"资深iOS开发者"}}";
NSArray * jsonArray = [WHC_Json arrayWithJson:json];
jsonArray = [WHC_Json arrayWithJsonData:[json
                    dataUsingEncoding:NSUTF8StringEncoding]];
```

### NSDictionary/NSArray对象转 Xml字符串
```objective-c
NSDictionary * REQHDR = @{@"TrnNum":@"INHB2015042900000001",@"TrnCode":@"1957747793"};
NSDictionary * REQBDY = @{@"OS":@"iPhone",@"App":@"CC",@"IconVersion":@""};
NSDictionary * ebMobileStartupInqR = @{@"REQHDR":REQHDR,@"REQBDY":REQBDY};
NSDictionary * xmlDic = @{@"ebMobileStartupInqRq":ebMobileStartupInqR};
//use one
NSString  * xmlStringOne = [WHC_Xml xmlWithDictionary:xmlDic];
//use two
NSString  * xmlStringTwo = [WHC_Xml xmlWithDictionary:xmlDic 
            rootAttribute:@"xmlns = \"http://ns.chinatrust.com.tw/XSD/CTCB/ESB/Message/BSMF/ebMobileStartupInqRq/01\""];

NSLog(@"xmlStringOne = %@",xmlStringOne);
//xmlStringOne =     NSString  * xml = @"<?xml version=\"1.0\" encoding=\"utf-8\"?>\
<ebMobileStartupInqRq >\
<REQHDR>\
<TrnNum>INHB2015042900000001</TrnNum>\
<TrnCode>1957747793</TrnCode>\
</REQHDR>\
<REQBDY>\
<OS>iPhone</OS>\
<App>CC</App>\
<IconVersion></IconVersion>\
</REQBDY>\
</ebMobileStartupInqRq>";


NSLog(@"xmlStringTwo = %@",xmlStringTwo);
//xmlStringTwo =     NSString  * xml = @"<?xml version=\"1.0\" encoding=\"utf-8\"?>\
<ebMobileStartupInqRq xmlns=\"http://ns.chinatrust.com.tw/XSD/CTCB/ESB/Message/BSMF/ebMobileStartupInqRq/01\">\
<REQHDR>\
<TrnNum>INHB2015042900000001</TrnNum>\
<TrnCode>1957747793</TrnCode>\
</REQHDR>\
<REQBDY>\
<OS>iPhone</OS>\
<App>CC</App>\
<IconVersion></IconVersion>\
</REQBDY>\
</ebMobileStartupInqRq>";

```

## License

WHCNetWorkKit is released under the MIT license. See LICENSE for details.


================================================
FILE: WHCNetWorkKit/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>FMWK</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>$(CURRENT_PROJECT_VERSION)</string>
	<key>NSPrincipalClass</key>
	<string></string>
</dict>
</plist>


================================================
FILE: WHCNetWorkKit/NSURLConnection/WHC_BaseOperation.h
================================================
//
//  WHC_BaseOperation.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

extern  NSTimeInterval const kWHCRequestTimeout;
extern  NSTimeInterval const kWHCDownloadSpeedDuring;
extern  CGFloat   const kWHCWriteSizeLenght;

extern  NSString * const _Nullable kWHCDomain;
extern  NSString * const _Nullable kWHCInvainUrlError;
extern  NSString * const _Nullable kWHCCalculateFolderSpaceAvailableFailError;
extern  NSString * const _Nullable kWHCErrorCode;
extern  NSString * const _Nullable kWHCFreeDiskSapceError;
extern  NSString * const _Nullable kWHCRequestRange;
extern  NSString * const _Nullable kWHCUploadCode;

/**
 * WHCHttpRequestStatus  网络请求状态枚举标识
 */

typedef NS_OPTIONS(NSUInteger, WHCHttpRequestStatus) {
    WHCHttpRequestNone = 1 << 0,
    WHCHttpRequestExecuting = 1 << 1,
    WHCHttpRequestCanceled = 1 << 2,
    WHCHttpRequestFinished = 1 << 3
};

/**
 * WHCHttpRequestStatus  网络请求类型枚举标识
 */

typedef NS_OPTIONS(NSUInteger, WHCHttpRequestType) {
    WHCHttpRequestGet = 1 << 4,
    WHCHttpRequestPost = 1 << 5,
    WHCHttpRequestFileDownload = 1 << 6,
    WHCHttpRequestFileUpload = 1 << 7
};


/**
 * WHCHttpRequestStatus  网络请求错误枚举标识
 */

typedef NS_OPTIONS(NSUInteger, WHCHttpErrorType) {
    WHCFreeDiskSpaceLack = 2 << 0,
    WHCGeneralError = 2 << 1,
    WHCCancelDownloadError = 2 << 2,
    WHCNetWorkError = 2 << 3
};

@class WHC_BaseOperation;
@class WHC_DownloadOperation;

/**
 * WHC_DownloadDelegate  网络下载回调代理
 */

@protocol  WHC_DownloadDelegate<NSObject>

@optional

/**
 * 下载应答回调方法
 * @param: operation 当前下载操作对象
 * @param: error 响应错误对象
 * @param: isOK 是否可以下载
 */

- (void)WHCDownloadResponse:(nonnull WHC_DownloadOperation *)operation
                      error:(nullable NSError *)error
                         ok:(BOOL)isOK;

/**
 * 下载过程回调方法
 * @param: operation 当前下载操作对象
 * @param: recvLength 当前接收下载字节数
 * @param: totalLength 总字节数
 * @param: speed 下载速度
 */

- (void)WHCDownloadProgress:(nonnull WHC_DownloadOperation *)operation
                       recv:(uint64_t)recvLength
                      total:(uint64_t)totalLength
                      speed:(nullable NSString *)speed;

/**
 * 下载结束回调方法
 * @param: operation 当前下载操作对象
 * @param: data 当前接收数据 (在requestType = WHCHttpRequestGet 该参数才有用 否则为nil)
 * @param: error 下载错误对象
 * @param: success 下载是否成功
 */

- (void)WHCDownloadDidFinished:(nonnull WHC_DownloadOperation *)operation
                          data:(nullable NSData *)data
                         error:(nullable NSError *)error
                       success:(BOOL)isSuccess;

@end


/**
 * 下载结束回调块
 * @param: operation 当前下载操作对象
 * @param: data 当前接收数据 (在requestType = WHCHttpRequestGet 该参数才有用 否则为nil)
 * @param: error 下载错误对象
 * @param: success 下载是否成功
 */

typedef void (^WHCDidFinished) (WHC_BaseOperation * _Nullable operation ,NSData * _Nullable data ,  NSError * _Nullable  error , BOOL isSuccess);

/**
 * 下载应答回调块
 * @param: operation 当前下载操作对象
 * @param: error 响应错误对象
 * @param: isOK 是否可以下载
 */

typedef void (^WHCResponse)(WHC_BaseOperation * _Nullable operation , NSError * _Nullable error ,BOOL isOK);

/**
 * 下载过程回调块
 * @param: operation 当前下载操作对象
 * @param: recvLength 当前接收下载字节数
 * @param: totalLength 总字节数
 * @param: speed 下载速度
 */

typedef void (^WHCProgress) (WHC_BaseOperation * _Nullable operation ,uint64_t recvLength , uint64_t totalLength , NSString * _Nullable speed);


/**
 * 说明: WHC_BaseOperation http网络操作对象基类,封装了底层通用操作细节共上层网络操作服务
 */
@interface WHC_BaseOperation : NSOperation <NSURLConnectionDataDelegate , NSURLConnectionDelegate>

/**
 * 网络参数编码类型
 */
@property (nonatomic , assign) NSUInteger     encoderType;

/**
 * 网络请求超时时长
 */
@property (nonatomic , assign) NSTimeInterval timeoutInterval;

/**
 * 网络请求缓存策略
 */
@property (nonatomic , assign) NSURLRequestCachePolicy cachePolicy;

/**
 * 网络请求Url
 */
@property (nonatomic , copy , nonnull) NSString * strUrl;

/**
 * 网络请求内容类型
 */
@property (nonatomic , copy , nonnull) NSString * contentType;

/**
 * POST网络请求参数
 */
@property (nonatomic , copy , nonnull) NSObject * postParam;

/**
 * http网络请求类型
 */
@property (nonatomic , assign) WHCHttpRequestType requestType;

/**
 * http网络请求对象
 */
@property (nonatomic , strong , nullable)NSMutableURLRequest     * urlRequest;

/**
 * http网络请求连接对象
 */
@property (nonatomic , strong , nullable)NSURLConnection         * urlConnection;

/**
 * http网络请求状态
 */
@property (nonatomic , assign)WHCHttpRequestStatus      requestStatus;

/**
 * http网络请求应答数据对象
 */
@property (nonatomic , strong , nullable)NSMutableData           * responseData;

/**
 * http网络请求应答数据对象长度
 */
@property (nonatomic , assign)uint64_t    responseDataLenght;

/**
 * http网络请求定时获取的数据长度
 */
@property (nonatomic , assign)uint64_t    orderTimeDataLenght;

/**
 * http网络请求接收的数据长度
 */
@property (nonatomic , assign)uint64_t    recvDataLenght;

/**
 * http网络下载时下载速度
 */

@property (nonatomic , strong , nullable)NSString  * networkSpeed;

/**
 * 下载完成回调块对象
 */
@property (nonatomic , copy , nullable )WHCDidFinished didFinishedBlock;

/**
 * 下载过程回调块对象
 */
@property (nonatomic , copy , nullable)WHCProgress progressBlock;

/**
 * 下载应答回调块对象
 */
@property (nonatomic, copy , nullable)WHCResponse responseBlock;

/**
 * 下载操作代理对象
 */
@property (nonatomic , weak, nullable)id<WHC_DownloadDelegate> delegate;

/**
 * 说明: 清空http 应答数据
 */
- (void)clearResponseData;


/**
 * 说明: 开始http请求
 */
- (void)startRequest;

/**
 * 说明: 开始http请求开启网速监控时钟
 */
- (void)startSpeedTimer;

/**
 * 说明: 结束http请求
 */
- (void)endRequest;

/**
 * 说明: 取消http请求
 */
- (void)cancelledRequest;

/**
 * 通用处理http应答错误
 * @param: response 当前网络操作应答对象
 */
- (BOOL)handleResponseError:(nullable NSURLResponse * )response;

/**
 * 添加依赖下载队列
 * @param: downloadOperation 将要添加的下载队列对象
 */
- (void)addDependOperation:(nonnull WHC_BaseOperation *)operation;

/**
 * 通用处理http请求过程错误
 * @param: error 当前网络错误对象
 * @param: code  错误代码
 */
- (void)handleReqeustError:(nullable NSError *)error code:(NSInteger)code;

/**
 * 说明: 计算网络速度
 */
- (void)calculateNetworkSpeed;


@end


================================================
FILE: WHCNetWorkKit/NSURLConnection/WHC_BaseOperation.m
================================================
//
//  WHC_BaseOperation.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import "WHC_BaseOperation.h"
#import "WHC_HttpManager.h"

NSTimeInterval const kWHCRequestTimeout = 60;
NSTimeInterval const kWHCDownloadSpeedDuring = 1.5;
CGFloat        const kWHCWriteSizeLenght = 1024 * 1024;
NSString  * const  kWHCDomain = @"WHC_HTTP_OPERATION";
NSString  * const  kWHCInvainUrlError = @"无效的url:%@";
NSString  * const  kWHCCalculateFolderSpaceAvailableFailError = @"计算文件夹存储空间失败";
NSString  * const  kWHCErrorCode = @"错误码:%ld";
NSString  * const  kWHCFreeDiskSapceError = @"磁盘可用空间不足需要存储空间:%llu";
NSString  * const  kWHCRequestRange = @"bytes=%lld-";
NSString  * const  kWHCUploadCode = @"WHC";

@interface WHC_BaseOperation () {
    NSTimer * _speedTimer;
    NSThread * _thread;
}

@end

@implementation WHC_BaseOperation

#pragma mark - 重写属性方法 -
- (void)setStrUrl:(NSString *)strUrl {
    _strUrl = nil;
    _strUrl = strUrl.copy;
    NSString * newUrl = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                              (CFStringRef)_strUrl,
                                                                                              (CFStringRef)@"!$&'()*-,-./:;=?@_~%#[]",
                                                                                              NULL,
                                                                                              kCFStringEncodingUTF8));
    _urlRequest = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:newUrl]];
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _timeoutInterval = kWHCRequestTimeout;
        _requestType = WHCHttpRequestGet;
        _requestStatus = WHCHttpRequestNone;
        _cachePolicy = NSURLRequestUseProtocolCachePolicy;
        _responseData = [NSMutableData data];
    }
    return self;
}

- (void)dealloc{
    [self cancelledRequest];
}


#pragma mark - 重写队列操作方法 -

- (void)start {
    @autoreleasepool {
        if ([NSURLConnection canHandleRequest:self.urlRequest]) {
            self.urlRequest.timeoutInterval = self.timeoutInterval;
            self.urlRequest.cachePolicy = self.cachePolicy;
            [_urlRequest setValue:self.contentType forHTTPHeaderField: @"Content-Type"];
            switch (self.requestType) {
                case WHCHttpRequestGet:
                case WHCHttpRequestFileDownload:{
                    [_urlRequest setHTTPMethod:@"GET"];
                }
                    break;
                case WHCHttpRequestPost:
                case WHCHttpRequestFileUpload:{
                    [_urlRequest setHTTPMethod:@"POST"];
                    if([WHC_HttpManager shared].cookie && [WHC_HttpManager shared].cookie.length > 0) {
                        [_urlRequest setValue:[WHC_HttpManager shared].cookie forHTTPHeaderField:@"Cookie"];
                    }
                    if (self.postParam != nil) {
                        NSData * paramData = nil;
                        if ([self.postParam isKindOfClass:[NSData class]]) {
                            paramData = (NSData *)self.postParam;
                        }else if ([self.postParam isKindOfClass:[NSString class]]) {
                            paramData = [((NSString *)self.postParam) dataUsingEncoding:self.encoderType allowLossyConversion:YES];
                        }
                        if (paramData) {
                            [_urlRequest setHTTPBody:paramData];
                            [_urlRequest setValue:[NSString stringWithFormat:@"%zd", paramData.length] forHTTPHeaderField: @"Content-Length"];
                        }
                    }
                }
                    break;
                default:
                    break;
            }
            if(self.urlConnection == nil){
                [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
                self.urlConnection = [[NSURLConnection alloc]initWithRequest:_urlRequest delegate:self startImmediately:NO];
            }
        }else {
            [self handleReqeustError:nil code:WHCGeneralError];
        }
    }
}

- (BOOL)isExecuting {
    return _requestStatus == WHCHttpRequestExecuting;
}

- (BOOL)isCancelled {
    BOOL isCancelled = _requestStatus == WHCHttpRequestCanceled ||
    _requestStatus == WHCHttpRequestFinished;
    if (isCancelled) {
        CFRunLoopStop(CFRunLoopGetCurrent());
        _thread = nil;
    }
    return isCancelled;
}

- (BOOL)isFinished {
    BOOL isFinished = _requestStatus == WHCHttpRequestFinished;
    if (isFinished) {
        CFRunLoopStop(CFRunLoopGetCurrent());
        _thread = nil;
    }
    return isFinished;
}

- (BOOL)isConcurrent{
    return YES;
}


#pragma mark - 公共方法 -

- (void)calculateNetworkSpeed {
    float downloadSpeed = (float)_orderTimeDataLenght / (kWHCDownloadSpeedDuring * 1024.0);
    _networkSpeed = [NSString stringWithFormat:@"%.1fKB/s", downloadSpeed];
    if (downloadSpeed >= 1024.0) {
        downloadSpeed = ((float)_orderTimeDataLenght / 1024.0) / (kWHCDownloadSpeedDuring * 1024.0);
        _networkSpeed = [NSString stringWithFormat:@"%.1fMB/s",downloadSpeed];
    }
    _orderTimeDataLenght = 0;
}


- (void)clearResponseData {
    [self.responseData resetBytesInRange:NSMakeRange(0, self.responseData.length)];
    [self.responseData setLength:0];
}

- (void)startRequest {
    [self willChangeValueForKey:@"isExecuting"];
    _requestStatus = WHCHttpRequestExecuting;
    [self didChangeValueForKey:@"isExecuting"];
    _thread = [NSThread currentThread];
    [_urlConnection start];
    CFRunLoopRun();
}

- (void)addDependOperation:(WHC_BaseOperation *)operation {
    [self addDependency:operation];
}

- (void)startSpeedTimer {
    if (!_speedTimer && (_requestType == WHCHttpRequestFileUpload ||
                         _requestType == WHCHttpRequestFileDownload ||
                         _requestType == WHCHttpRequestGet)) {
        _speedTimer = [NSTimer scheduledTimerWithTimeInterval:kWHCDownloadSpeedDuring
                                                       target:self
                                                     selector:@selector(calculateNetworkSpeed)
                                                     userInfo:nil
                                                      repeats:YES];
        [self calculateNetworkSpeed];
    }
}

- (BOOL)handleResponseError:(NSURLResponse * )response {
    BOOL isError = NO;
    NSHTTPURLResponse  *  headerResponse = (NSHTTPURLResponse *)response;
    if(headerResponse.statusCode >= 400){
        isError = YES;
        self.requestStatus = WHCHttpRequestFinished;
        if (self.requestType != WHCHttpRequestFileDownload) {
            [self cancelledRequest];
            NSError * error = [NSError errorWithDomain:kWHCDomain
                                                  code:WHCGeneralError
                                              userInfo:@{NSLocalizedDescriptionKey:
                                                             [NSString stringWithFormat:kWHCErrorCode,
                                                              (long)headerResponse.statusCode]}];
            dispatch_async(dispatch_get_main_queue(), ^{
                if (self.didFinishedBlock) {
                    self.didFinishedBlock(self, nil , error , NO);
                    self.didFinishedBlock = nil;
                }else if (self.delegate &&
                          [self.delegate respondsToSelector:@selector(WHCDownloadDidFinished:data:error:success:)]) {
                    if (headerResponse.statusCode == 404) {
                        [[WHC_HttpManager shared].failedUrls addObject: self.strUrl];
                    }
                    [self.delegate WHCDownloadDidFinished:(WHC_DownloadOperation *)self data:nil error:error success:NO];
                }
            });
        }
    }else {
        _responseDataLenght = headerResponse.expectedContentLength;
        [self startSpeedTimer];
    }
    return isError;
}

- (void)endRequest {
    self.didFinishedBlock = nil;
    self.progressBlock = nil;
    [self cancelledRequest];
}

- (void)cancelledRequest{
    if (_urlConnection) {
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        [_urlConnection unscheduleFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [_urlConnection cancel];
        _urlConnection = nil;
        [self willChangeValueForKey:@"isCancelled"];
        [self willChangeValueForKey:@"isFinished"];
        _requestStatus = WHCHttpRequestFinished;
        [self didChangeValueForKey:@"isFinished"];
        [self didChangeValueForKey:@"isCancelled"];
        if (_requestType == WHCHttpRequestFileUpload ||
            _requestType == WHCHttpRequestFileDownload) {
            if (_speedTimer) {
                [_speedTimer invalidate];
                [_speedTimer fire];
                _speedTimer = nil;
            }
        }
    }
}

- (void)handleReqeustError:(NSError *)error code:(NSInteger)code {
    if(error == nil){
        error = [[NSError alloc]initWithDomain:kWHCDomain
                                          code:code
                                      userInfo:@{NSLocalizedDescriptionKey:
                                                     [NSString stringWithFormat:kWHCInvainUrlError,self.strUrl]}];
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.didFinishedBlock) {
            self.didFinishedBlock (self, nil, error , NO);
            self.didFinishedBlock = nil;
        }else if (self.delegate &&
                  [self.delegate respondsToSelector:@selector(WHCDownloadDidFinished:data:error:success:)]) {
            [self.delegate WHCDownloadDidFinished:(WHC_DownloadOperation *)self data:nil error:error success:NO];
        }
    });
    
}

@end


================================================
FILE: WHCNetWorkKit/NSURLConnection/WHC_DownloadOperation.h
================================================
//
//  WHC_DownloadOperation.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import "WHC_BaseOperation.h"


@interface WHC_DownloadOperation : WHC_BaseOperation

/**
 * 下载操作下标
 */

@property (nonatomic , assign)NSInteger index;
/**
 * 保存文件路径
 */
@property (nonatomic , copy)NSString       *   saveFilePath;

/**
 * 保存文件名
 */
@property (nonatomic , copy)NSString       *   saveFileName;
/**
 * 下载是否完成标记
 */
@property (nonatomic , assign , readonly)BOOL               isDownloadCompleted;
/**
 * 文件实际总长度
 */
@property (nonatomic , assign , readonly)uint64_t           fileTotalLenght;
/**
 * 文件实际总长度
 */
@property (nonatomic , assign)uint64_t                      actualFileSizeLenght;
/**
 * 本地缓存文件总长度
 */
@property (nonatomic , assign)uint64_t                      localFileLenght;

/**
 * 下载任务是否删除
 */
@property (nonatomic , assign)BOOL isDeleted;

/**
 * 函数说明: 取消当前下载任务
 * @param: isDelete 取消下载任务的同时是否删除下载缓存的文件
 */

- (void)cancelDownloadTaskAndDeleteFile:(BOOL)isDelete;

/**
 * 函数说明: 下载请求响应
 * @param: response 下载请求应答对象
 */

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
@end


================================================
FILE: WHCNetWorkKit/NSURLConnection/WHC_DownloadOperation.m
================================================
//
//  WHC_DownloadOperation.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import "WHC_DownloadOperation.h"

@interface WHC_DownloadOperation () {
    uint64_t                  _localFileSizeLenght;   //文件尺寸大小
    NSFileHandle            * _fileHandle;         //文件句柄
}

@end

@implementation WHC_DownloadOperation

- (void)dealloc {
}

#pragma mark - 重写属性方法 -

- (NSString *)saveFileName {
    if (_saveFileName) {
        return _saveFileName;
    }else{
        return [self.strUrl lastPathComponent];
    }
}

- (NSString *)saveFilePath {
    return [_saveFilePath stringByAppendingString:self.saveFileName];
}

- (uint64_t)downloadLenght {
    return self.recvDataLenght;
}

- (uint64_t)fileTotalLenght {
    return _actualFileSizeLenght;
}

- (void)start {
    __autoreleasing  NSError  * error = nil;
    NSFileManager  * fm = [NSFileManager defaultManager];
    if(![fm fileExistsAtPath:self.saveFilePath]) {
        [fm createFileAtPath:self.saveFilePath contents:nil attributes:nil];
    }else {
        _localFileSizeLenght = [[fm attributesOfItemAtPath:self.saveFilePath error:&error] fileSize];
        NSString  * strRange = [NSString stringWithFormat:kWHCRequestRange ,_localFileSizeLenght];
        [self.urlRequest setValue:strRange forHTTPHeaderField:@"Range"];
    }
    
    if(error == nil) {
        _fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.saveFilePath];
        [_fileHandle seekToEndOfFile];
    }else {
        NSLog(@"%@",kWHCCalculateFolderSpaceAvailableFailError);
    }
    [super start];
    [self startRequest];
}

#pragma mark - 私有方法

- (uint64_t)calculateFreeDiskSpace{
    uint64_t  freeDiskLen = 0;
    NSString * docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSFileManager  * fm   = [NSFileManager defaultManager];
    NSDictionary   * dict = [fm attributesOfFileSystemForPath:docPath error:nil];
    if(dict){
        freeDiskLen = [dict[NSFileSystemFreeSize] unsignedLongLongValue];
    }
    return freeDiskLen;
}

- (NSInteger)getCode {
    NSInteger code = WHCGeneralError;
    NSFileManager * fm = [NSFileManager defaultManager];
    if (self.recvDataLenght > 0 ||
        [[fm attributesOfItemAtPath:self.saveFilePath error:nil] fileSize] > 100) {
        code = WHCCancelDownloadError;
    }
    return code;
}

- (void)removeDownloadFile {
    NSFileManager  * fm = [NSFileManager defaultManager];
    if([fm fileExistsAtPath:self.saveFilePath]){
        [fm removeItemAtPath:self.saveFilePath error:nil];
    }
}

#pragma mark - 公共处理方法 -

- (void)cancelDownloadTaskAndDeleteFile:(BOOL)isDelete {
    _isDeleted = isDelete;
    if(self.responseData.length > 0 && _fileHandle){
        [_fileHandle writeData:self.responseData];
        [self clearResponseData];
    }
    self.requestStatus = WHCHttpRequestFinished;
    [self cancelledRequest];
    if(isDelete){
        [self removeDownloadFile];
    }
    NSError * error = nil;
    if (!isDelete) {
        error = [NSError errorWithDomain:kWHCDomain
                            code:[self getCode]
                        userInfo:@{NSLocalizedDescriptionKey:@"下载已取消"}];
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.didFinishedBlock) {
            self.didFinishedBlock(self, nil , error , NO);
            self.didFinishedBlock = nil;
        }else if (self.delegate &&
                  [self.delegate respondsToSelector:@selector(WHCDownloadDidFinished:data:error:success:)]) {
            [self.delegate WHCDownloadDidFinished:self data:nil error:error success:NO];
        }
    });
    
}

- (void)appExitHandleDownloadFile:(NSNotification *)notify {
    if (self.urlConnection) {
        [self connectionDidFinishLoading:self.urlConnection];
    }
}

- (void)cancelledRequest{
    [super cancelledRequest];
    if (_fileHandle) {
        [_fileHandle synchronizeFile];
        [_fileHandle closeFile];
        _fileHandle = nil;
    }
}

- (void)handleReqeustError:(NSError *)error code:(NSInteger)code {
    if (code != WHCCancelDownloadError) {
        [self removeDownloadFile];
    }
    [super handleReqeustError:error code:code];
}

#pragma mark - 实现网络代理方法 -

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    BOOL  isCancel = YES;
    NSError  * error = nil;
    NSInteger code = WHCGeneralError;
    if (![self handleResponseError:response]){
        isCancel = NO;
        _actualFileSizeLenght = response.expectedContentLength + _localFileSizeLenght;
        
        if([self calculateFreeDiskSpace] < _actualFileSizeLenght){
            error = [[NSError alloc]initWithDomain:kWHCDomain
                                              code:WHCFreeDiskSpaceLack
                                          userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:kWHCFreeDiskSapceError,_actualFileSizeLenght]}];
            [self removeDownloadFile];
            code = WHCFreeDiskSpaceLack;
            isCancel = YES;
            goto WHC1;
        }else{
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(appExitHandleDownloadFile:)
                                                         name:UIApplicationWillTerminateNotification
                                                       object:nil];
            self.recvDataLenght = _localFileSizeLenght;
            [self clearResponseData];
            goto WHC2;
        }
    }else {
    WHC1:
        [self cancelDownloadTaskAndDeleteFile:NO];
        error = [NSError errorWithDomain:kWHCDomain code:code userInfo:@{NSLocalizedDescriptionKey:response.description}];
        
    WHC2:
        dispatch_async(dispatch_get_main_queue() , ^{
            if (self.responseBlock) {
                self.responseBlock(self, error ,!isCancel);
                self.responseBlock = nil;
            }else if (self.delegate &&
                      [self.delegate respondsToSelector:@selector(WHCDownloadResponse:error:ok:)]) {
                [self.delegate WHCDownloadResponse:self error:error ok:!isCancel];
            }
        });
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.responseData appendData:data];
    self.recvDataLenght += data.length;
    self.orderTimeDataLenght += data.length;
    if(self.responseData.length > kWHCWriteSizeLenght && _fileHandle){
        [_fileHandle writeData:self.responseData];
        [self clearResponseData];
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.progressBlock) {
            self.progressBlock(self ,self.recvDataLenght , _actualFileSizeLenght , self.networkSpeed);
        }else if (self.delegate &&
                  [self.delegate respondsToSelector:@selector(WHCDownloadProgress:recv:total:speed:)]) {
            [self.delegate WHCDownloadProgress:self recv:self.recvDataLenght total:_actualFileSizeLenght speed:self.networkSpeed];
        }
    });
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    if(_fileHandle){
        [_fileHandle writeData:self.responseData];
        [self clearResponseData];
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.didFinishedBlock) {
            self.didFinishedBlock(self, nil , nil, YES);
            self.didFinishedBlock = nil;
        }else if (self.delegate &&
                  [self.delegate respondsToSelector:@selector(WHCDownloadDidFinished:data:error:success:)]) {
            [self.delegate WHCDownloadDidFinished:self data:nil error:nil success:YES];
        }
    });
    
    [self cancelledRequest];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [self cancelledRequest];
    [self handleReqeustError:error code:[self getCode]];
}

@end


================================================
FILE: WHCNetWorkKit/NSURLConnection/WHC_HttpManager.h
================================================
//
//  WHC_HttpManager.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import <Foundation/Foundation.h>
#import "WHC_HttpOperation.h"
#import "WHC_DownloadOperation.h"
#import "Reachability.h"

/**
 * 默认下载并发数量
 */

extern const NSInteger kWHCDefaultDownloadNumber;

/**
 * 说明: WHC_HttpManager http请求管理类 (单例设计模式 支持POST/GET 请求 文件上传 文件下载)
 */

@interface WHC_HttpManager : NSObject

/**
 * 说明: 当前是否是等待下载状态
 */
- (BOOL)waitingDownload;

/**
 * 网络管理单例对象
 */
+ (nonnull instancetype)shared;

/**
 * 网络参数编码类型
 */

@property (nonatomic , assign) NSUInteger     encoderType;

/**
 * 网络请求缓存策略
 */

@property (nonatomic , assign) NSURLRequestCachePolicy cachePolicy;

/**
 * 网络请求超时时长
 */

@property (nonatomic , assign) NSTimeInterval timeoutInterval;

/**
 * 网络请求内容类型
 */
@property (nonatomic , copy , nonnull)  NSString *  contentType;

/**
 * 网络请求404错误集合(下次再遇到则不请求)
 */

@property (nonatomic , strong , nullable) NSMutableSet * failedUrls;

/**
 * 网络请求会话id对象
 */
@property (nonatomic , strong , nullable) NSString * cookie;

/**
 * 创建文件保存路径
 * @param: savePath 文件路径
 */
- (BOOL)createFileSavePath:(nonnull NSString *)savePath;

/**
 * 生成通用错误对象
 * @param: message 错误信息
 */

- (nonnull NSError *)error:(nonnull NSString *)message;

/**
 * 自动处理生成正确文件名
 * @param: saveFileName 保存文件名
 * @param: strUrl 下载地址
 */

- (nullable NSString *)handleFileName:(nonnull NSString *)saveFileName url:(nonnull NSString *)strUrl;

/**
 * 当前网络状态
 */

@property (nonatomic , assign)NetworkStatus        networkStatus;


/**
 * 注册监听设备网络状态
 */
- (void)registerNetworkStatusMoniterEvent;

/**
 * GET 请求操作
 * @param: strUrl 请求地址
 * @param: finishedBlock 完成块
 */

- (nullable WHC_HttpOperation *)get:(nonnull NSString *)strUrl
               didFinished:(nullable WHCDidFinished)finishedBlock;


/**
 * GET 请求操作
 * @param: strUrl 请求地址
 * @param: processBlock 请求过程块
 * @param: finishedBlock 完成块
 */

- (nullable WHC_HttpOperation *)get:(nonnull NSString *)strUrl
                            process:(nullable WHCProgress) processBlock
                        didFinished:(nullable WHCDidFinished)finishedBlock;

/**
 * POST 请求操作
 * @param: strUrl 请求地址
 * @param: param 请求参数
 * @param: finishedBlock 完成块
 */

- (nullable WHC_HttpOperation *)post:(nonnull NSString *)strUrl
                               param:(nullable NSString *)param
                         didFinished:(nullable WHCDidFinished)finishedBlock;

/**
 * POST 请求操作
 * @param: strUrl 请求地址
 * @param: param 请求参数
 * @param: processBlock 请求过程块
 * @param: finishedBlock 完成块
 */

- (nullable WHC_HttpOperation *)post:(nonnull NSString *)strUrl
                               param:(nullable NSString *)param
                             process:(nullable WHCProgress)processBlock
                         didFinished:(nullable WHCDidFinished)finishedBlock;

/**
 * 文件上传 请求操作
 * @param: strUrl 请求地址
 * @param: param 请求参数
 * @param: finishedBlock 完成块
 */

- (nullable WHC_HttpOperation *)upload:(nonnull NSString *)strUrl
                                 param:(nullable NSDictionary *)paramDict
                           didFinished:(nullable WHCDidFinished)finishedBlock;

/**
 * 文件上传 请求操作
 * @param: strUrl 请求地址
 * @param: param 请求参数
 * @param: processBlock 请求过程块
 * @param: finishedBlock 完成块
 */

- (nullable WHC_HttpOperation *)upload:(nonnull NSString *)strUrl
                                 param:(nullable NSDictionary *)paramDict
                               process:(nullable WHCProgress)processBlock
                           didFinished:(nullable WHCDidFinished)finishedBlock;



/**
 * 说明: 执行下载任务 (存储时使用默认文件名)
 * @param strUrl 下载地址
 * @param savePath 下载缓存路径
 * @param delegate 下载响应代理
 */

- (nullable WHC_DownloadOperation *)download:(nonnull NSString *)strUrl
                                    savePath:(nonnull NSString *)savePath
                                    delegate:(nullable id<WHC_DownloadDelegate>)delegate;

/**
 * 说明: 执行下载任务
 * @param strUrl 下载地址
 * @param savePath 下载缓存路径
 * @param saveFileName 下载保存文件名
 * @param delegate 下载响应代理
 */

- (nullable WHC_DownloadOperation *)download:(nonnull NSString *)strUrl
                                    savePath:(nonnull NSString *)savePath
                                saveFileName:(nullable NSString *)saveFileName
                                    delegate:(nullable id<WHC_DownloadDelegate>)delegate;

/**
 * 说明: 执行下载任务 (存储时使用默认文件名)
 * @param strUrl 下载地址
 * @param savePath 下载缓存路径
 * @param responseBlock 下载响应回调
 * @param processBlock 下载过程回调
 * @param didFinishedBlock 下载完成回调
 */

- (nullable WHC_DownloadOperation *)download:(nonnull NSString *)strUrl
                                    savePath:(nonnull NSString *)savePath
                                    response:(nullable WHCResponse)responseBlock
                                     process:(nullable WHCProgress)processBlock
                                 didFinished:(nullable WHCDidFinished)finishedBlock;

/**
 * 说明: 执行下载任务
 * @param strUrl 下载地址
 * @param savePath 下载缓存路径
 * @param saveFileName 下载保存文件名
 * @param responseBlock 下载响应回调
 * @param processBlock 下载过程回调
 * @param didFinishedBlock 下载完成回调
 */

- (nullable WHC_DownloadOperation *)download:(nonnull NSString *)strUrl
                                    savePath:(nonnull NSString *)savePath
                                saveFileName:(nullable NSString *)saveFileName
                                    response:(nullable WHCResponse) responseBlock
                                     process:(nullable WHCProgress) processBlock
                                 didFinished:(nullable WHCDidFinished) finishedBlock;




/**
 * 说明: 添加上传文件数据
 * @param: data 文件数据
 * @param: fileName 文件名
 * @param: mimeType 文件类型
 * @param: key 上传标识 (这个必须和服务端对应)
 */

- (void)addUploadFileData:(nonnull NSObject *)data
             withFileName:(nonnull NSString *)fileName
                 mimeType:(nonnull NSString *)mimeType
                   forKey:(nonnull NSString *)key;

/**
 * 说明: 添加上传文件
 * @param: filePath 本地文件路径
 * @param: key 上传标识 (这个必须和服务端对应)
 */

- (void)addUploadFile:(nonnull NSString *)filePath
               forKey:(nonnull NSString *)key;


/**
 * 说明: 取消http请求
 * @param: url http 地址
 */

- (void)cancelHttpRequestWithUrl:(nonnull NSString *)url ;

/**
 * 说明: 返回指定文件名下载对象
 * @param: fileName 下载文件名
 */

- (nullable WHC_DownloadOperation *)downloadOperationWithFileName:(nonnull NSString *)fileName;

/**
 * 说明:设置最大下载数量(该方法必须在开始下载之前调用)
 * @param: count 下载并发数量
 */

- (void)setMaxDownloadQueueCount:(NSUInteger)count;

/**
 * 说明:返回下载中心最大同时下载操作个数
 */

- (NSInteger)currentDownloadCount;

/**
 * 说明:取消所有当前下载任务
 * @param isDelete 是否删除缓存文件
 */

- (void)cancelAllDownloadTaskAndDelFile:(BOOL)isDelete;

/**
 * 说明:取消指定正下载url的下载
 * @param isDelete 是否删除缓存文件
 */

- (void)cancelDownloadWithDownloadUrl:(nonnull NSString *)strUrl
                           deleteFile:(BOOL)isDelete;
/**
 * 说明:取消指定正下载文件名的下载
 * @param isDelete 是否删除缓存文件
 */

- (void)cancelDownloadWithFileName:(nonnull NSString *)fileName
                        deleteFile:(BOOL)isDelete;


/**
 * 说明:替换当前回调通过传递要下载的文件名(当从控制器B进入到控制器C然后在控制器C中进行下载,然后下载过程中突然退出到控制器B,在又进入到控制器C,这个时候还是在下载但是代理对象和之前的那个控制器C不是一个对象所以要替换)
 * @param responseBlock 下载响应回调
 * @param processBlock 下载过程回调
 * @param didFinishedBlock 下载完成回调
 * @param fileName 文件名
 */

- (nullable WHC_DownloadOperation *)replaceCurrentDownloadOperationBlockResponse:(nullable WHCResponse)responseBlock
                                             process:(nullable WHCProgress)processBlock
                                         didFinished:(nullable WHCDidFinished)didFinishedBlock
                                            fileName:(nonnull NSString *)fileName;

/**
 * 说明:替换当前回调通过传递要下载的文件名(当从控制器B进入到控制器C然后在控制器C中进行下载,然后下载过程中突然退出到控制器B,在又进入到控制器C,这个时候还是在下载但是代理对象和之前的那个控制器C不是一个对象所以要替换)
 * @param delegate 下载回调新代理
 * @param fileName 文件名
 */

- (nullable WHC_DownloadOperation *)replaceCurrentDownloadOperationDelegate:(nullable id<WHC_DownloadDelegate>)delegate
                                       fileName:(nonnull NSString *)fileName;

/**
 * 说明:替换当前所有下载代理(当从控制器B进入到控制器C然后在控制器C中进行下载,然后下载过程中突然退出到控制器B,在又进入到控制器C,这个时候还是在下载但是代理对象和之前的那个控制器C不是一个对象所以要替换)
 * @param responseBlock 下载响应回调
 * @param processBlock 下载过程回调
 * @param didFinishedBlock 下载完成回调
 */
- (nullable WHC_DownloadOperation *)replaceAllDownloadOperationBlockResponse:(nullable WHCResponse)responseBlock
                                         process:(nullable WHCProgress)processBlock
                                     didFinished:(nullable WHCDidFinished)didFinishedBlock;

/**
 * 说明:替换当前所有下载代理(当从控制器B进入到控制器C然后在控制器C中进行下载,然后下载过程中突然退出到控制器B,在又进入到控制器C,这个时候还是在下载但是代理对象和之前的那个控制器C不是一个对象所以要替换)
 * @param delegate 下载回调新代理
 */

- (nullable WHC_DownloadOperation *)replaceAllDownloadOperationDelegate:(nullable id<WHC_DownloadDelegate>)delegate;

/**
 * 说明:通过要下载的文件名来判断当前是否在进行下载任务
 * @param fileName 正在下载的文件名
 */

- (BOOL)existDownloadOperationTaskWithUrl:(nonnull NSString *)strUrl;


/**
 * 说明:通过要下载的文件名来判断当前是否在进行下载任务
 * @param strUrl 正在下载的url
 */

- (BOOL)existDownloadOperationTaskWithFileName:(nonnull NSString *)fileName;

/**
 * 获取文件名格式通过Url
 * @param: downloadUrl 下载路径
 */

- (nullable NSString *)fileFormatWithUrl:(nonnull NSString *)downloadUrl;

/**
 * 生成http请求原始参数对象
 * @param: paramDictionary 参数字典
 */

- (nonnull NSString*)createHttpParam:(nonnull NSDictionary *)paramDictionary;

@end


================================================
FILE: WHCNetWorkKit/NSURLConnection/WHC_HttpManager.m
================================================
//
//  WHC_HttpManager.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import "WHC_HttpManager.h"
#import <MobileCoreServices/MobileCoreServices.h>

const NSInteger kWHCDefaultDownloadNumber = 3;

@interface WHC_HttpManager () {
    NSOperationQueue     * _httpOperationQueue;
    NSOperationQueue     * _fileDownloadOperationQueue;
    Reachability         * _internetReachability;
    
    NSMutableArray       * _fileDataArr;
    NSMutableArray       * _uploadParamArr;
    NSMutableData        * _uploadPostData;
}


@end

@implementation WHC_HttpManager

+ (nonnull instancetype)shared {
    static  WHC_HttpManager * WHCHttpManager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        WHCHttpManager = [WHC_HttpManager new];
    });
    return WHCHttpManager;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _httpOperationQueue = [NSOperationQueue new];
        _httpOperationQueue.maxConcurrentOperationCount = 20;
        _failedUrls = [NSMutableSet set];
        _encoderType = NSUTF8StringEncoding;
        _cachePolicy = NSURLRequestUseProtocolCachePolicy;
        _contentType = @"application/x-www-form-urlencoded";
    }
    return self;
}



#pragma mark - 网络状态监听 -
- (void)registerNetworkStatusMoniterEvent {
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(reachabilityChanged:)
                                                 name:kReachabilityChangedNotification
                                               object:nil];
    
    _internetReachability = [Reachability reachabilityForInternetConnection];
    [_internetReachability startNotifier];
    [self updateInterfaceWithReachability:_internetReachability];
}

- (void)updateInterfaceWithReachability:(Reachability*)internetReachability{
    NetworkStatus netStatus = [internetReachability currentReachabilityStatus];
    self.networkStatus = netStatus;
    switch (netStatus) {
        case NotReachable:{
            for (WHC_DownloadOperation * downloadOperation in _fileDownloadOperationQueue.operations) {
                [downloadOperation cancelDownloadTaskAndDeleteFile:NO];
            }
            for (WHC_BaseOperation * httpOperation in _httpOperationQueue.operations) {
                [httpOperation cancelledRequest];
            }
            [[[UIAlertView alloc]initWithTitle:nil
                                       message:@"当前网络不可用请检查网络设置"
                                      delegate:nil cancelButtonTitle:@"确定"
                             otherButtonTitles:nil, nil] show];
        }
            break;
        case ReachableViaWiFi:
            NSLog(@"====当前网络状态为Wifi=======");
            break;
        case ReachableViaWWAN:
            NSLog(@"====当前网络状态为3G=======");
            break;
    }
}

- (void)reachabilityChanged:(NSNotification *)notifiy{
    Reachability* curReach = [notifiy object];
    NSParameterAssert([curReach isKindOfClass:[Reachability class]]);
    [self updateInterfaceWithReachability:curReach];
}

#pragma mark - get请求 -

- (nullable WHC_HttpOperation *)get:(nonnull NSString *)strUrl
               didFinished:(nullable WHCDidFinished)finishedBlock {
    return [self get:strUrl process:nil didFinished:finishedBlock];
}

- (nullable WHC_HttpOperation *)get:(nonnull NSString *)strUrl
                   process:(nullable WHCProgress) processBlock
               didFinished:(nullable WHCDidFinished)finishedBlock {
    WHC_HttpOperation * getOperation = nil;
    if (strUrl != nil && ![_failedUrls containsObject:strUrl]) {
        getOperation = [WHC_HttpOperation new];
        getOperation.requestType = WHCHttpRequestGet;
        getOperation.progressBlock = processBlock;
        getOperation.strUrl = strUrl;
        __weak typeof(self) weakSelf = self;
        getOperation.didFinishedBlock = ^(WHC_BaseOperation *operation, NSData *data, NSError *error, BOOL isSuccess) {
            if (!isSuccess && error.code == 404) {
                [weakSelf.failedUrls addObject:strUrl];
            }
            if (finishedBlock) {
                finishedBlock(operation , data , error , isSuccess);
            }
        };
        [self setHttpOperation:getOperation];
        [_httpOperationQueue addOperation:getOperation];
    }else {
        if (finishedBlock) {
            __autoreleasing NSError * error = [self error:[NSString stringWithFormat:@"%@:请求失败",strUrl]];
            finishedBlock(nil , nil , error , NO);
        }
    }
    return getOperation;
}

#pragma mark - post请求 -

- (nullable WHC_HttpOperation *)post:(nonnull NSString *)strUrl
                      param:(nullable NSString *)param
                didFinished:(nullable WHCDidFinished)finishedBlock {
    return [self post:strUrl param:param process:nil didFinished:finishedBlock];
}

- (nullable WHC_HttpOperation *)post:(nonnull NSString *)strUrl
                      param:(nullable NSString *)param
                    process:(nullable WHCProgress) processBlock
                didFinished:(nullable WHCDidFinished)finishedBlock {
    WHC_HttpOperation * postOperation = nil ;
    if (strUrl != nil && ![_failedUrls containsObject:strUrl]) {
        postOperation = [WHC_HttpOperation new];
        postOperation.requestType = WHCHttpRequestPost;
        postOperation.progressBlock = processBlock;
        postOperation.postParam = param;
        postOperation.strUrl = strUrl;
        __weak typeof(self) weakSelf = self;
        postOperation.didFinishedBlock = ^(WHC_BaseOperation *operation, NSData *data, NSError *error, BOOL isSuccess) {
            if (!isSuccess && error.code == 404) {
                [weakSelf.failedUrls addObject:strUrl];
            }
            if (finishedBlock) {
                finishedBlock(operation , data , error , isSuccess);
            }
        };
        [self setHttpOperation:postOperation];
        [_httpOperationQueue addOperation:postOperation];
    }else {
        if (finishedBlock) {
            __autoreleasing NSError * error = [self error:[NSString stringWithFormat:@"%@:请求失败",strUrl]];
            finishedBlock(nil , nil , error , NO);
        }
    }

    return postOperation;
}

#pragma mark - 文件上传 -

- (nullable WHC_HttpOperation *)upload:(nonnull NSString *)strUrl
                        param:(nullable NSDictionary *)paramDict
                  didFinished:(nullable WHCDidFinished)finishedBlock {
    return [self upload:strUrl
                  param:paramDict
                process:nil
            didFinished:finishedBlock];
}
/**
 说明:文件上传开始
 strUrl:上传路径
 param:上传附带参数
 callBack:上传结束回调
 */
- (nullable WHC_HttpOperation *)upload:(nonnull NSString *)strUrl
                        param:(nullable NSDictionary *)paramDict
                      process:(nullable WHCProgress) processBlock
                  didFinished:(nullable WHCDidFinished)finishedBlock {
    [self setPostParamDict:paramDict];
    [self buildMultipartFormDataPostBody];
    WHC_HttpOperation * uploadOperation = nil ;
    if (strUrl != nil && ![_failedUrls containsObject:strUrl]) {
        uploadOperation = [WHC_HttpOperation new];
        [self setHttpOperation:uploadOperation];
        uploadOperation.requestType = WHCHttpRequestFileUpload;
        uploadOperation.progressBlock = processBlock;
        uploadOperation.strUrl = strUrl;
        uploadOperation.postParam = _uploadPostData;
        __weak typeof(self) weakSelf = self;
        uploadOperation.didFinishedBlock = ^(WHC_BaseOperation *operation, NSData *data, NSError *error, BOOL isSuccess) {
            [_uploadParamArr removeAllObjects];
            [_fileDataArr removeAllObjects];
            [_uploadPostData resetBytesInRange:NSMakeRange(0, _uploadPostData.length)];
            [_uploadPostData setLength:0];
            if (!isSuccess && error.code == 404) {
                [weakSelf.failedUrls addObject:strUrl];
            }
            if (finishedBlock) {
                finishedBlock(operation , data , error , isSuccess);
            }
        };
        NSString * charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
        uploadOperation.contentType = [NSString stringWithFormat:@"multipart/form-data; charset=%@; boundary=%@", charset, kWHCUploadCode];
        [_httpOperationQueue addOperation:uploadOperation];
    }else {
        if (finishedBlock) {
            __autoreleasing NSError * error = [self error:[NSString stringWithFormat:@"%@:请求失败",strUrl]];
            finishedBlock(nil , nil , error , NO);
        }
    }
    return uploadOperation;
}

#pragma mark - 文件下载 -

- (nullable WHC_DownloadOperation *)download:(nonnull NSString *)strUrl
                                    savePath:(nonnull NSString *)savePath
                                    delegate:(nullable id<WHC_DownloadDelegate>)delegate {
    return [self download:strUrl savePath:savePath saveFileName:nil delegate:delegate];
}


- (nullable WHC_DownloadOperation *)download:(nonnull NSString *)strUrl
                                    savePath:(nonnull NSString *)savePath
                                saveFileName:(nullable NSString *)saveFileName
                                    delegate:(nullable id<WHC_DownloadDelegate>)delegate {
    
    WHC_DownloadOperation  * downloadOperation = nil;
    NSString * fileName = nil;
    if (strUrl != nil && ![_failedUrls containsObject:strUrl]) {
        fileName = [self handleFileName:saveFileName url:strUrl];
        for (WHC_DownloadOperation * tempDownloadOperation in _fileDownloadOperationQueue.operations) {
            if ([fileName isEqualToString:tempDownloadOperation.saveFileName]){
                __autoreleasing NSError * error = [self error:[NSString stringWithFormat:@"%@:已经在下载中",fileName]];
                if (delegate && [delegate respondsToSelector:@selector(WHCDownloadResponse:error:ok:)]) {
                    [delegate WHCDownloadResponse:tempDownloadOperation error:error ok:NO];
                } else if (delegate && [delegate respondsToSelector:@selector(WHCDownloadDidFinished:data:error:success:)]) {
                    [delegate WHCDownloadDidFinished:tempDownloadOperation data:nil error:error success:NO];
                }
                return tempDownloadOperation;
            }
        }
        if([self createFileSavePath:savePath]) {
            downloadOperation = [WHC_DownloadOperation new];
            downloadOperation.requestType = WHCHttpRequestGet;
            downloadOperation.saveFileName = fileName;
            downloadOperation.saveFilePath = savePath;
            downloadOperation.delegate = delegate;
            downloadOperation.strUrl = strUrl;
            [self setHttpOperation:downloadOperation];
            [_fileDownloadOperationQueue addOperation:downloadOperation];
        }
    }else {
        __autoreleasing NSError * error = [self error:[NSString stringWithFormat:@"%@:请求失败",strUrl]];
        if (delegate &&
            [delegate respondsToSelector:@selector(WHCDownloadDidFinished:data:error:success:)]) {
            [delegate WHCDownloadDidFinished:downloadOperation data:nil error:error success:NO];
        }
    }
    return downloadOperation;
}

/**
 参数说明:
 url:下载路径
 savePath:文件本地存储路径
 delegate:下载状态监控代理
 */
- (nullable WHC_DownloadOperation *)download:(nonnull NSString *)strUrl
                           savePath:(nonnull NSString *)savePath
                            response:(nullable WHCResponse) responseBlock
                            process:(nullable WHCProgress) processBlock
                        didFinished:(nullable WHCDidFinished) finishedBlock {
    
    return [self download:strUrl
                 savePath:savePath
             saveFileName:nil
                 response:responseBlock
                  process:processBlock
              didFinished:finishedBlock];
}

/**
 参数说明:
 url:下载路径
 savePath:文件本地存储路径
 savefileName:下载要存储的文件名
 delegate:下载状态监控代理
 */
- (nullable WHC_DownloadOperation *)download:(nonnull NSString *)strUrl
                                    savePath:(nonnull NSString *)savePath
                                saveFileName:(nullable NSString *)saveFileName
                                    response:(nullable WHCResponse) responseBlock
                                     process:(nullable WHCProgress) processBlock
                                 didFinished:(nullable WHCDidFinished) finishedBlock {
NSLog(@"_fileDownloadOperationQueue.operations = %d",_fileDownloadOperationQueue.operations.count);
    WHC_DownloadOperation  * downloadOperation = nil;
    NSString * fileName = nil;
    if (strUrl != nil && ![_failedUrls containsObject:strUrl]) {
        fileName = [self handleFileName:saveFileName url:strUrl];
        for (WHC_DownloadOperation * tempDownloadOperation in _fileDownloadOperationQueue.operations) {
            if ([fileName isEqualToString:tempDownloadOperation.saveFileName]){
                __autoreleasing NSError * error = [self error:[NSString stringWithFormat:@"%@:已经在下载中",fileName]];
                if (responseBlock) {
                    responseBlock(tempDownloadOperation, error, NO);
                } else if (finishedBlock) {
                    finishedBlock(tempDownloadOperation ,nil, error, NO);
                }
                return tempDownloadOperation;
            }
        }
        if([self createFileSavePath:savePath]) {
            downloadOperation = [WHC_DownloadOperation new];
            downloadOperation.requestType = WHCHttpRequestGet;
            downloadOperation.saveFileName = fileName;
            downloadOperation.saveFilePath = savePath;
            downloadOperation.progressBlock = processBlock;
            downloadOperation.responseBlock = responseBlock;
            downloadOperation.strUrl = strUrl;
            __weak typeof(self) weakSelf = self;
            downloadOperation.didFinishedBlock = ^(WHC_BaseOperation *operation,
                                                   NSData *data,
                                                   NSError *error,
                                                   BOOL isSuccess) {
                if (!isSuccess && error.code == 404) {
                    [weakSelf.failedUrls addObject:strUrl];
                }
                if (finishedBlock) {
                    finishedBlock(operation , data , error , isSuccess);
                }
            };
            [self setHttpOperation:downloadOperation];
            [_fileDownloadOperationQueue addOperation:downloadOperation];
        }
    }else {
        __autoreleasing NSError * error = [self error:[NSString stringWithFormat:@"%@:请求失败",strUrl]];
        if (responseBlock) {
            responseBlock(downloadOperation , error , NO);
        }else if (finishedBlock) {
            finishedBlock(downloadOperation , nil , error , NO);
        }
    }
    return downloadOperation;
}



#pragma mark - 文件上传工具方法 -

/*
 说明:添加上传文件数据,可多次调用添加上传多个文件
 data:可以是二进制数据也可以是本地文件路径
 fileName:文件名称
 mimeType:文件类型如图片(image/jpeg)
 key:关键字名称这个必须和服务端对应
 */
- (void)addUploadFileData:(nonnull NSObject *)data
             withFileName:(nonnull NSString *)fileName
                 mimeType:(nonnull NSString *)mimeType
                   forKey:(nonnull NSString *)key {
    
    if (_fileDataArr == nil) {
        _fileDataArr = [NSMutableArray array];
    }
    if (!mimeType) {
        mimeType = @"application/octet-stream";
    }
    
    NSMutableDictionary *fileInfo = [NSMutableDictionary dictionaryWithCapacity:4];
    [fileInfo setValue:key forKey:@"key"];
    [fileInfo setValue:fileName forKey:@"fileName"];
    [fileInfo setValue:mimeType forKey:@"contentType"];
    [fileInfo setValue:data forKey:@"data"];
    
    [_fileDataArr addObject:fileInfo];
}

/**
 说明:添加上传文件路径,可多次调用添加上传多个文件
 filePath:文件路径
 key:关键字名称这个必须和服务端对应
 */
- (void)addUploadFile:(nonnull NSString *)filePath
               forKey:(nonnull NSString *)key {
    NSFileManager  * fm = [NSFileManager defaultManager];
    if([fm fileExistsAtPath:filePath]){
        NSString  * fileName = filePath.lastPathComponent;
        NSString  * mimeType = [self mimeTypeForFileAtPath:filePath];
        [self addUploadFileData:filePath withFileName:fileName mimeType:mimeType forKey:key];
    }
}

#pragma mark - 文件下载工具方法 -

- (BOOL)waitingDownload {
    return _fileDownloadOperationQueue.operations.count > kWHCDefaultDownloadNumber;
}

- (nullable NSString *)handleFileName:(NSString *)saveFileName url:(NSString *)strUrl {
    if (!_fileDownloadOperationQueue) {
        _fileDownloadOperationQueue = [NSOperationQueue new];
        _fileDownloadOperationQueue.maxConcurrentOperationCount = kWHCDefaultDownloadNumber;
    }
    NSString * fileName = saveFileName;
    if(saveFileName){
        NSString * format = [self fileFormatWithUrl:strUrl];
        if(format && ![format isEqualToString:[NSString stringWithFormat:@".%@",
                                    [[saveFileName componentsSeparatedByString:@"."] lastObject]]]){
            fileName = [NSString stringWithFormat:@"%@%@",saveFileName,format];
        }
    }
    return fileName;
}

//返回指定文件名下载对象
- (nullable WHC_DownloadOperation *)downloadOperationWithFileName:(nonnull NSString *)fileName {
    WHC_DownloadOperation * downloadOperation = nil;
    for (WHC_DownloadOperation * tempDownloadOperation in _fileDownloadOperationQueue.operations) {
        if([tempDownloadOperation.saveFileName isEqualToString:fileName]){
            downloadOperation = tempDownloadOperation;
            break;
        }
    }
    return downloadOperation;
}

/**
 note:该方法必须在开始下载之前调用
 说明:
 设置最大下载数量
 */
- (void)setMaxDownloadQueueCount:(NSUInteger)count {
    _fileDownloadOperationQueue.maxConcurrentOperationCount = count;
}

/**
 说明:返回下载中心最大同时下载操作个数
 */
- (NSInteger)currentDownloadCount {
    return _fileDownloadOperationQueue.maxConcurrentOperationCount;
}

/**
 说明:
 取消所有正下载并是否取消删除文件
 */
- (void)cancelAllDownloadTaskAndDelFile:(BOOL)isDelete {
    for (WHC_DownloadOperation * operation in _fileDownloadOperationQueue.operations) {
        [operation cancelDownloadTaskAndDeleteFile:isDelete];
    }
}

/**
 说明:
 取消指定正下载url的下载
 */
- (void)cancelDownloadWithDownloadUrl:(nonnull NSString *)strUrl deleteFile:(BOOL)isDelete {
    for(WHC_DownloadOperation * operation in _fileDownloadOperationQueue.operations){
        if ([operation.strUrl isEqualToString:strUrl]) {
            [operation cancelDownloadTaskAndDeleteFile:isDelete];
            break;
        }
    }
}

/**
 说明:
 取消指定正下载文件名的下载
 */
- (void)cancelDownloadWithFileName:(nonnull NSString *)fileName deleteFile:(BOOL)isDelete {
    for(WHC_DownloadOperation * operation in _fileDownloadOperationQueue.operations){
        if([operation.saveFileName isEqualToString:fileName]){
            [operation cancelDownloadTaskAndDeleteFile:isDelete];
            break;
        }
    }
}


/**
 说明:
 替换当前代理通过要下载的文件名
 使用情景:(当从控制器B进入到控制器C然后在控制器C中进行下载,然后下载过程中突然退出到控制器B,
 在又进入到控制器C,这个时候还是在下载但是代理对象和之前的那个控制器C不是一个对象所以要替换)
 */


- (WHC_DownloadOperation *)replaceCurrentDownloadOperationBlockResponse:(nullable WHCResponse)responseBlock
                                             process:(nullable WHCProgress)processBlock
                                         didFinished:(nullable WHCDidFinished)didFinishedBlock
                                            fileName:(nonnull NSString *)fileName {
    for (WHC_DownloadOperation * downloadOperation in _fileDownloadOperationQueue.operations) {
        if([downloadOperation.saveFileName isEqualToString:fileName]){
            downloadOperation.delegate = nil;
            downloadOperation.progressBlock = processBlock;
            downloadOperation.responseBlock = responseBlock;
            downloadOperation.didFinishedBlock = didFinishedBlock;
            return downloadOperation;
        }
    }
    return nil;
}

- (WHC_DownloadOperation *)replaceCurrentDownloadOperationDelegate:(nullable id<WHC_DownloadDelegate>)delegate
                                       fileName:(nonnull NSString *)fileName {
    for (WHC_DownloadOperation * downloadOperation in _fileDownloadOperationQueue.operations) {
        if([downloadOperation.saveFileName isEqualToString:fileName]){
            downloadOperation.progressBlock = nil;
            downloadOperation.responseBlock = nil;
            downloadOperation.didFinishedBlock = nil;
            downloadOperation.delegate = delegate;
            return downloadOperation;
        }
    }
    return nil;
}

//替换所有当前下载代理
- (WHC_DownloadOperation *)replaceAllDownloadOperationBlockResponse:(nullable WHCResponse)responseBlock
                                         process:(nullable WHCProgress)processBlock
                                     didFinished:(nullable WHCDidFinished)didFinishedBlock {
    if (_fileDownloadOperationQueue.operations.count > 0) {
        for (WHC_DownloadOperation * downloadOperation in _fileDownloadOperationQueue.operations) {
            downloadOperation.delegate = nil;
            downloadOperation.progressBlock = processBlock;
            downloadOperation.responseBlock = responseBlock;
            downloadOperation.didFinishedBlock = didFinishedBlock;
        }
        return nil;
    }
    return nil;
}

- (WHC_DownloadOperation *)replaceAllDownloadOperationDelegate:(nullable id<WHC_DownloadDelegate>)delegate {
    if (_fileDownloadOperationQueue.operations.count > 0) {
        for (WHC_DownloadOperation * downloadOperation in _fileDownloadOperationQueue.operations) {
            downloadOperation.progressBlock = nil;
            downloadOperation.responseBlock = nil;
            downloadOperation.didFinishedBlock = nil;
            downloadOperation.delegate = delegate;
        }
        return nil;
    }
    return nil;
}


/**
 说明:
 通过要下载的文件名来判断当前是否在进行下载任务
 */
- (BOOL)existDownloadOperationTaskWithFileName:(nonnull NSString *)fileName {
    BOOL  result = NO;
    for (WHC_DownloadOperation * downloadOperation in _fileDownloadOperationQueue.operations) {
        if([downloadOperation.saveFileName isEqualToString:fileName]){
            result = YES;
            break;
        }
    }
    return result;
}

- (BOOL)existDownloadOperationTaskWithUrl:(nonnull NSString *)strUrl {
    BOOL  result = NO;
    for (WHC_DownloadOperation * downloadOperation in _fileDownloadOperationQueue.operations) {
        if([downloadOperation.strUrl isEqualToString:strUrl]){
            result = YES;
            break;
        }
    }
    return result;
}

#pragma mark - 公共方法 -

- (void)cancelHttpRequestWithUrl:(nonnull NSString *)url {
    for (WHC_BaseOperation * operation in _httpOperationQueue.operations) {
        if ([operation.strUrl isEqualToString:url]) {
            [operation endRequest];
        }
    }
}

- (nullable NSString *)fileFormatWithUrl:(nonnull NSString *)downloadUrl {
    NSArray  * strArr = [downloadUrl componentsSeparatedByString:@"."];
    if(strArr && strArr.count > 0){
        NSString * suffix = strArr.lastObject;
        if (suffix.length > 7) {
            return nil;
        }
        return [NSString stringWithFormat:@".%@",strArr.lastObject].lowercaseString;
    }else{
        return nil;
    }
}

- (nonnull NSString*)createHttpParam:(nonnull NSDictionary *)paramDictionary {
    NSString *postString=@"";
    for(NSString *key in [paramDictionary allKeys]){
        NSString *value = [paramDictionary objectForKey:key];
        postString = [postString stringByAppendingFormat:@"%@=%@&",key,value];
    }
    if([postString length] > 1){
        postString = [postString substringToIndex:[postString length]-1];
    }
    return postString;
}

#pragma mark - 私有方法 -

- (__autoreleasing NSError *)error:(nonnull NSString *)message {
    __autoreleasing NSError  * error = [[NSError alloc]initWithDomain:kWHCDomain
                                                                 code:WHCGeneralError
                                                             userInfo:@{NSLocalizedDescriptionKey:
                                                                            message}];
    return error;
}

- (void)setHttpOperation:(WHC_BaseOperation *)httpOperation {
    httpOperation.encoderType = _encoderType;
    httpOperation.cachePolicy = _cachePolicy;
    httpOperation.contentType = _contentType;
    httpOperation.timeoutInterval = _timeoutInterval;
}

- (BOOL)createFileSavePath:(nonnull NSString *)savePath {
    BOOL  result = YES;
    if(savePath != nil && savePath.length > 0){
        NSFileManager  * fm = [NSFileManager defaultManager];
        if(![fm fileExistsAtPath:savePath]){
            __autoreleasing NSError *error = nil;
            [fm createDirectoryAtPath:savePath
          withIntermediateDirectories:YES
                           attributes:@{NSFileProtectionKey : NSFileProtectionNone}
                                error:&error];
            if(error){
                result = NO;
            }
        }
    }else{
        result = NO;
    }
    return result;
}

#pragma mark - 上传文件私有方法

- (nullable NSString *)mimeTypeForFileAtPath:(nullable NSString *)path{
    if (![[NSFileManager defaultManager]fileExistsAtPath:path]) {
        return nil;
    }
    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[path pathExtension], NULL);
    CFStringRef MIMEType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType);
    CFRelease(UTI);
    if (!MIMEType) {
        return @"application/octet-stream";
    }
    return  (__bridge NSString *)MIMEType;
}


- (void)appendPostString:(nullable NSString *)string{
    if(_uploadPostData == nil){
        _uploadPostData = [NSMutableData data];
    }
    [_uploadPostData appendData:[string dataUsingEncoding:NSUTF8StringEncoding]];
}


- (void)setPostParamDict:(nullable NSDictionary *)paramDict{
    
    if (paramDict == nil) {
        return;
    }
    if (_uploadParamArr == nil) {
        _uploadParamArr = [NSMutableArray array];
    }else{
        [_uploadParamArr removeAllObjects];
    }
    NSArray  * keyArr = paramDict.allKeys;
    if(keyArr){
        for (NSString * strKey in keyArr) {
            NSMutableDictionary *keyValuePair = [NSMutableDictionary dictionaryWithCapacity:2];
            [keyValuePair setValue:strKey forKey:@"key"];
            [keyValuePair setValue:[[paramDict objectForKey:strKey] description] forKey:@"value"];
            [_uploadParamArr addObject:keyValuePair];
        }
    }
}

- (void)appendPostData:(nullable NSData *)data{
    if ([data length] == 0) {
        return;
    }
    if(_uploadPostData == nil){
        _uploadPostData = [NSMutableData data];
    }
    [_uploadPostData appendData:data];
}

- (void)appendPostDataFromFile:(nullable NSString *)file {
    if(_uploadPostData == nil){
        _uploadPostData = [NSMutableData data];
    }
    NSFileManager  * fm = [NSFileManager defaultManager];
    if([fm fileExistsAtPath:file]){
        NSInputStream *stream = [[NSInputStream alloc] initWithFileAtPath:file];
        [stream open];
        NSUInteger bytesRead;
        while ([stream hasBytesAvailable]) {
            unsigned char buffer[1024 * 256];
            bytesRead = [stream read:buffer maxLength:sizeof(buffer)];
            if (bytesRead == 0) {
                break;
            }
            [_uploadPostData appendData:[NSData dataWithBytes:buffer length:bytesRead]];
        }
        [stream close];
    }
}

- (void)buildMultipartFormDataPostBody {
    if(_uploadParamArr == nil){
        _uploadParamArr = [NSMutableArray array];
    }
    NSString *stringBoundary = kWHCUploadCode;
    [self appendPostString:[NSString stringWithFormat:@"--%@\r\n",stringBoundary]];
    NSUInteger i = 0;
    NSString *endItemBoundary = [NSString stringWithFormat:@"\r\n--%@\r\n",stringBoundary];
    // 设置文件数据
    for (NSDictionary *val in _fileDataArr) {
        
        [self appendPostString:[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", val[@"key"], val[@"fileName"]]];
        [self appendPostString:[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", val[@"contentType"]]];
        
        id data = val[@"data"];
        if ([data isKindOfClass:[NSString class]]) {
            [self appendPostDataFromFile:data];
        } else {
            [self appendPostData:data];
        }
        [self appendPostString:@"\r\n"];
        i++;
        //添加分隔符在边界除了最后一个元素
        if (i != [_fileDataArr count]) {
            [self appendPostString:endItemBoundary];
        }
    }
    [self appendPostString:endItemBoundary];
    //设置普通参数
    i = 0;
    for (NSDictionary *val in _uploadParamArr) {
        [self appendPostString:[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",val[@"key"]]];
        [self appendPostString:val[@"value"]];
        [self appendPostString:@"\r\n"];
        i++;
        //添加分隔符在边界除了最后一个元素
        if (i != _uploadParamArr.count) {
            [self appendPostString:endItemBoundary];
        }
    }
    [self appendPostString:[NSString stringWithFormat:@"\r\n--%@--\r\n",stringBoundary]];
}

@end


================================================
FILE: WHCNetWorkKit/NSURLConnection/WHC_HttpOperation.h
================================================
//
//  WHC_HttpOperation.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import "WHC_BaseOperation.h"


@interface WHC_HttpOperation : WHC_BaseOperation

@end


================================================
FILE: WHCNetWorkKit/NSURLConnection/WHC_HttpOperation.m
================================================
//
//  WHC_HttpOperation.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//

#import "WHC_HttpOperation.h"
#import "WHC_HttpManager.h"
@interface WHC_HttpOperation ()  {
    
}

@end

@implementation WHC_HttpOperation

#pragma mark - 重写操作方法 -

- (void)start {
    [super start];
    [self startRequest];
}

- (void)cancelledRequest{
    [super cancelledRequest];
}

#pragma mark - 实现网络代理方法 -

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    if (![self handleResponseError:response]) {
        NSHTTPURLResponse  *  headerResponse = (NSHTTPURLResponse *)response;
        NSDictionary * fields = [headerResponse allHeaderFields];
        NSString * newCookie = fields[@"Set-Cookie"];
        if (newCookie) {
            if([WHC_HttpManager shared].cookie == nil){
                [WHC_HttpManager shared].cookie = newCookie.copy;
            }else if ([WHC_HttpManager shared].cookie != newCookie){
                [WHC_HttpManager shared].cookie = nil;
                [WHC_HttpManager shared].cookie = newCookie.copy;
            }
        }
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.responseData appendData:data];
    if (self.requestType == WHCHttpRequestGet) {
        self.recvDataLenght += data.length;
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.progressBlock) {
                self.progressBlock(self, self.recvDataLenght , self.responseDataLenght , self.networkSpeed);
            }
        });
    }
}

- (void)connection:(NSURLConnection *)connection
           didSendBodyData:(NSInteger)bytesWritten
         totalBytesWritten:(NSInteger)totalBytesWritten
        totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {
    
    if (self.requestType == WHCHttpRequestFileUpload) {
        [self startSpeedTimer];
        self.orderTimeDataLenght += bytesWritten;
        self.recvDataLenght += bytesWritten;
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.progressBlock) {
                self.progressBlock(self, self.recvDataLenght , totalBytesWritten , self.networkSpeed);
            }
        });
    }
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.didFinishedBlock) {
            self.didFinishedBlock(self ,self.responseData , nil, YES);
         }
        self.didFinishedBlock = nil;
    });
    [self cancelledRequest];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    self.delegate = nil;
    [self cancelledRequest];
    [self handleReqeustError:error code:WHCGeneralError];
}

@end


================================================
FILE: WHCNetWorkKit/NSURLSession/WHC_DownloadSessionTask.h
================================================
//
//  WHC_DownloadSessionTask.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/12/7.
//  Copyright © 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import "WHC_DownloadOperation.h"

/**
 * 说明: WHC_DownloadSessionTask  单个后台下载任务类
 */

@interface WHC_DownloadSessionTask : WHC_DownloadOperation

/**
 * 当前后台下载任务对象
 */
@property (nonatomic , strong)NSURLSessionDownloadTask * downloadTask;

/**
 * 函数说明: 取消当前下载任务
 * @param: isDelete 取消下载任务的同时是否删除下载缓存的文件
 */

- (void)cancelDownloadTaskAndDeleteFile:(BOOL)isDelete;

/**
 * 函数说明: 处理下载应答
 * @param: response 下载应答对象
 */

- (void)handleResponse:(NSURLResponse *)response;
@end


================================================
FILE: WHCNetWorkKit/NSURLSession/WHC_DownloadSessionTask.m
================================================
//
//  WHC_DownloadSessionTask.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/12/7.
//  Copyright © 2015年 吴海超. All rights reserved.
//
/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import "WHC_DownloadSessionTask.h"

@implementation WHC_DownloadSessionTask

- (void)cancelDownloadTaskAndDeleteFile:(BOOL)isDelete {
    if (isDelete) {
        [_downloadTask cancel];
    }
}

- (void)handleResponse:(NSURLResponse *)response {
    [self connection:nil didReceiveResponse:response];
}

@end


================================================
FILE: WHCNetWorkKit/NSURLSession/WHC_SessionDownloadManager.h
================================================
//
//  WHC_SessionDownloadOperation.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/30.
//  Copyright © 2015年 吴海超. All rights reserved.
//
/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */
#import <Foundation/Foundation.h>
#import "WHC_DownloadSessionTask.h"

/**
 * 说明: WHC_SessionDownloadManager 后台下载管理类 单例设计模式
 */

@interface WHC_SessionDownloadManager : NSObject

/**
 * 说明: 当前是否是等待下载状态
 */
- (BOOL)waitingDownload;

/**
 * 后台下载配置字符
 */
@property (nonnull ,nonatomic , copy)NSString * bundleIdentifier;

/**
 * 下载对象单例
 */
+ (nonnull instancetype)shared;

/**
 * 说明: 执行下载任务 (存储时使用默认文件名)
 * @param strUrl 下载地址
 * @param savePath 下载缓存路径
 * @param delegate 下载响应代理
 */
- (nullable WHC_DownloadSessionTask *)download:(nonnull NSString *)strUrl
                                      savePath:(nonnull NSString *)savePath
                                      delegate:(nullable id<WHC_DownloadDelegate>)delegate;

/**
 * 说明: 执行下载任务
 * @param strUrl 下载地址
 * @param savePath 下载缓存路径
 * @param saveFileName 下载保存文件名
 * @param delegate 下载响应代理
 */

- (nullable WHC_DownloadSessionTask *)download:(nonnull NSString *)strUrl
                                      savePath:(nonnull NSString *)savePath
                                  saveFileName:(nullable NSString *)saveFileName
                                      delegate:(nullable id<WHC_DownloadDelegate>)delegate;

/**
 * 说明: 执行下载任务 (存储时使用默认文件名)
 * @param strUrl 下载地址
 * @param savePath 下载缓存路径
 * @param responseBlock 下载响应回调
 * @param processBlock 下载过程回调
 * @param didFinishedBlock 下载完成回调
 */

- (nullable WHC_DownloadSessionTask *)download:(nonnull NSString *)strUrl
                                      savePath:(nonnull NSString *)savePath
                                      response:(nullable WHCResponse)responseBlock
                                       process:(nullable WHCProgress)processBlock
                                   didFinished:(nullable WHCDidFinished)finishedBlock;

/**
 * 说明: 执行下载任务
 * @param strUrl 下载地址
 * @param savePath 下载缓存路径
 * @param saveFileName 下载保存文件名
 * @param responseBlock 下载响应回调
 * @param processBlock 下载过程回调
 * @param didFinishedBlock 下载完成回调
 */

- (nullable WHC_DownloadSessionTask *)download:(nonnull NSString *)strUrl
                                      savePath:(nonnull NSString *)savePath
                                  saveFileName:(nullable NSString *)saveFileName
                                      response:(nullable WHCResponse) responseBlock
                                       process:(nullable WHCProgress) processBlock
                                   didFinished:(nullable WHCDidFinished) finishedBlock;

/**
 * 说明:取消所有当前下载任务
 * @param isDelete 是否删除缓存文件
 */

- (void)cancelAllDownloadTaskAndDelFile:(BOOL)isDelete;

/**
 * 说明:取消指定正下载url的下载
 * @param isDelete 是否删除缓存文件
 */

- (void)cancelDownloadWithDownloadUrl:(nonnull NSString *)strUrl deleteFile:(BOOL)isDelete;

/**
 * 说明:取消指定正下载文件名的下载
 * @param isDelete 是否删除缓存文件
 */

- (void)cancelDownloadWithFileName:(nonnull NSString *)fileName deleteFile:(BOOL)isDelete;


/**
 * 说明:替换当前回调通过传递要下载的文件名(当从控制器B进入到控制器C然后在控制器C中进行下载,然后下载过程中突然退出到控制器B,在又进入到控制器C,这个时候还是在下载但是代理对象和之前的那个控制器C不是一个对象所以要替换)
 * @param responseBlock 下载响应回调
 * @param processBlock 下载过程回调
 * @param didFinishedBlock 下载完成回调
 * @param fileName 文件名
 */


- (nullable WHC_DownloadSessionTask *)replaceCurrentDownloadOperationBlockResponse:(nullable WHCResponse)responseBlock
                                             process:(nullable WHCProgress)processBlock
                                         didFinished:(nullable WHCDidFinished)didFinishedBlock
                                            fileName:(nonnull NSString *)fileName;

/**
 * 说明:替换当前回调通过传递要下载的文件名(当从控制器B进入到控制器C然后在控制器C中进行下载,然后下载过程中突然退出到控制器B,在又进入到控制器C,这个时候还是在下载但是代理对象和之前的那个控制器C不是一个对象所以要替换)
 * @param delegate 下载回调新代理
 * @param fileName 文件名
 */

- (nullable WHC_DownloadSessionTask *)replaceCurrentDownloadOperationDelegate:(nullable id<WHC_DownloadDelegate>)delegate
                                       fileName:(nonnull NSString *)fileName;

/**
 * 说明:替换当前所有下载代理(当从控制器B进入到控制器C然后在控制器C中进行下载,然后下载过程中突然退出到控制器B,在又进入到控制器C,这个时候还是在下载但是代理对象和之前的那个控制器C不是一个对象所以要替换)
 * @param responseBlock 下载响应回调
 * @param processBlock 下载过程回调
 * @param didFinishedBlock 下载完成回调
 */

- (nullable WHC_DownloadSessionTask *)replaceAllDownloadOperationBlockResponse:(nullable WHCResponse)responseBlock
                                         process:(nullable WHCProgress)processBlock
                                     didFinished:(nullable WHCDidFinished)didFinishedBlock;

/**
 * 说明:替换当前所有下载代理(当从控制器B进入到控制器C然后在控制器C中进行下载,然后下载过程中突然退出到控制器B,在又进入到控制器C,这个时候还是在下载但是代理对象和之前的那个控制器C不是一个对象所以要替换)
 * @param delegate 下载回调新代理
 */

- (nullable WHC_DownloadSessionTask *)replaceAllDownloadOperationDelegate:(nullable id<WHC_DownloadDelegate>)delegate;


/**
 * 说明:通过要下载的文件名来判断当前是否在进行下载任务
 * @param fileName 正在下载的文件名
 */

- (BOOL)existDownloadOperationTaskWithFileName:(nonnull NSString *)fileName;

/**
 * 说明:通过要下载的文件名来判断当前是否在进行下载任务
 * @param strUrl 正在下载的url
 */

- (BOOL)existDownloadOperationTaskWithUrl:(nonnull NSString *)strUrl;

@end


================================================
FILE: WHCNetWorkKit/NSURLSession/WHC_SessionDownloadManager.m
================================================
//
//  WHC_SessionDownloadOperation.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/30.
//  Copyright © 2015年 吴海超. All rights reserved.
//
/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */
#import "WHC_SessionDownloadManager.h"
#import "WHC_DownloadSessionTask.h"
#import "WHC_HttpManager.h"


@interface WHC_SessionDownloadManager () <NSURLSessionDataDelegate , NSURLSessionDelegate>{
    NSOperationQueue *  _asynQueue;
    NSURLSession     *  _downloadSession;
    NSMutableArray   *  _downloadTaskArr;
    NSMutableDictionary * _resumeDataDictionary;
    NSFileManager    *  _fileManager;
    NSMutableDictionary * _etagDictionary;
    NSString * _resumeDataPath;
}

@end

@implementation WHC_SessionDownloadManager

+ (instancetype)shared {
    static WHC_SessionDownloadManager * downloadManager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        downloadManager = [WHC_SessionDownloadManager new];
    });
    return downloadManager;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _asynQueue = [NSOperationQueue new];
        _asynQueue.maxConcurrentOperationCount = kWHCDefaultDownloadNumber;
        _downloadTaskArr = [NSMutableArray array];
        _resumeDataDictionary = [NSMutableDictionary dictionary];
        _fileManager = [NSFileManager defaultManager];
        _etagDictionary = [NSMutableDictionary dictionary];
        _resumeDataPath = [NSString stringWithFormat:@"%@/Library/Caches/WHCResumeDataCache/",NSHomeDirectory()];
        BOOL isDirectory = YES;
        if (![_fileManager fileExistsAtPath:_resumeDataPath isDirectory:&isDirectory]) {
            [_fileManager createDirectoryAtPath:_resumeDataPath
          withIntermediateDirectories:YES
                           attributes:@{NSFileProtectionKey:NSFileProtectionNone} error:nil];
        }
    }
    return self;
}

- (void)setBundleIdentifier:(nonnull NSString *)identifier {
    if (_downloadSession == nil) {
        _bundleIdentifier = nil;
        _bundleIdentifier = identifier.copy;
        NSURLSessionConfiguration * configuration;
        if ([NSURLSessionConfiguration respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]){
            configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:_bundleIdentifier];
        }else {
            configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:_bundleIdentifier];
        }
        configuration.discretionary = YES;
        _downloadSession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:_asynQueue];
        
    }
}

- (BOOL)waitingDownload {
    return _asynQueue.operations.count > kWHCDefaultDownloadNumber;
}

#pragma mark - 下载对外接口

- (nullable WHC_DownloadSessionTask *)download:(nonnull NSString *)strUrl
                                    savePath:(nonnull NSString *)savePath
                                    delegate:(nullable id<WHC_DownloadDelegate>)delegate {
    return [self download:strUrl savePath:savePath saveFileName:nil delegate:delegate];
}


- (nullable WHC_DownloadSessionTask *)download:(nonnull NSString *)strUrl
                                    savePath:(nonnull NSString *)savePath
                                saveFileName:(nullable NSString *)saveFileName
                                    delegate:(nullable id<WHC_DownloadDelegate>)delegate {
    WHC_DownloadSessionTask  * downloadTask = nil;
    NSString * fileName = nil;
    if (strUrl != nil && ![[WHC_HttpManager shared].failedUrls containsObject:strUrl]) {
        fileName = [[WHC_HttpManager shared] handleFileName:saveFileName url:strUrl];
        for (WHC_DownloadSessionTask * tempDownloadTask in _downloadTaskArr) {
            if ([fileName isEqualToString: tempDownloadTask.saveFileName]){
                __autoreleasing NSError * error = [[WHC_HttpManager shared] error:[NSString stringWithFormat:@"%@:已经在下载中",fileName]];
                if (delegate && [delegate respondsToSelector:@selector(WHCDownloadResponse:error:ok:)]) {
                    [delegate WHCDownloadResponse:tempDownloadTask error:error ok:NO];
                } else if (delegate && [delegate respondsToSelector:@selector(WHCDownloadDidFinished:data:error:success:)]) {
                    [delegate WHCDownloadDidFinished:tempDownloadTask data:nil error:error success:NO];
                }
                return tempDownloadTask;
            }
        }
        if([[WHC_HttpManager shared] createFileSavePath:savePath]) {
            
            downloadTask = [WHC_DownloadSessionTask new];
            downloadTask.requestType = WHCHttpRequestFileDownload;
            downloadTask.saveFileName = fileName;
            downloadTask.saveFilePath = savePath;
            downloadTask.delegate = delegate;
            downloadTask.strUrl = strUrl;
            downloadTask.delegate = delegate;
            [self startDownload:downloadTask];
        }
    }else {
        __autoreleasing NSError * error = [[WHC_HttpManager shared] error:[NSString stringWithFormat:@"%@:请求失败",strUrl]];
        if (delegate &&
            [delegate respondsToSelector:@selector(WHCDownloadDidFinished:data:error:success:)]) {
            [delegate WHCDownloadDidFinished:downloadTask data:nil error:error success:NO];
        }
    }
    return downloadTask;
    
}

- (nullable WHC_DownloadSessionTask *)download:(nonnull NSString *)strUrl
                                    savePath:(nonnull NSString *)savePath
                                    response:(nullable WHCResponse)responseBlock
                                     process:(nullable WHCProgress)processBlock
                                 didFinished:(nullable WHCDidFinished)finishedBlock {
    return nil;
}

- (nullable WHC_DownloadSessionTask *)download:(nonnull NSString *)strUrl
                                    savePath:(nonnull NSString *)savePath
                                saveFileName:(nullable NSString *)saveFileName
                                    response:(nullable WHCResponse) responseBlock
                                     process:(nullable WHCProgress) processBlock
                                 didFinished:(nullable WHCDidFinished) finishedBlock {
    WHC_DownloadSessionTask  * downloadTask = nil;
    NSString * fileName = nil;
    if (strUrl != nil && ![[WHC_HttpManager shared].failedUrls containsObject:strUrl]) {
        fileName = [[WHC_HttpManager shared] handleFileName:saveFileName url:strUrl];
        for (WHC_DownloadSessionTask * tempDownloadTask in _downloadTaskArr) {
            if ([fileName isEqualToString:tempDownloadTask.saveFileName]){
                __autoreleasing NSError * error = [[WHC_HttpManager shared] error:[NSString stringWithFormat:@"%@:已经在下载中",fileName]];
                if (responseBlock) {
                    responseBlock(tempDownloadTask, error, NO);
                } else if (finishedBlock) {
                    finishedBlock(tempDownloadTask ,nil, error, NO);
                }
                return tempDownloadTask;
            }
        }
        if([[WHC_HttpManager shared] createFileSavePath:savePath]) {
            downloadTask = [WHC_DownloadSessionTask new];
            downloadTask.requestType = WHCHttpRequestFileDownload;
            downloadTask.saveFileName = fileName;
            downloadTask.saveFilePath = savePath;
            downloadTask.progressBlock = processBlock;
            downloadTask.responseBlock = responseBlock;
            downloadTask.strUrl = strUrl;
            downloadTask.didFinishedBlock = ^(WHC_BaseOperation *operation,
                                                   NSData *data,
                                                   NSError *error,
                                                   BOOL isSuccess) {
                if (!isSuccess && error.code == 404) {
                    [[WHC_HttpManager shared].failedUrls addObject:strUrl];
                }
                if (finishedBlock) {
                    finishedBlock(operation , data , error , isSuccess);
                }
            };
            [self startDownload:downloadTask];
        }
    }else {
        __autoreleasing NSError * error = [[WHC_HttpManager shared] error:[NSString stringWithFormat:@"%@:请求失败",strUrl]];
        if (responseBlock) {
            responseBlock(downloadTask , error , NO);
        }else if (finishedBlock) {
            finishedBlock(downloadTask , nil , error , NO);
        }
    }
    return downloadTask;
}

#pragma mark - 私有方法

- (NSString *)getResumeDataFilePath:(NSString *)fileName {
    if (fileName && fileName.length > 0) {
        return [NSString stringWithFormat:@"%@%@",_resumeDataPath , fileName];
    }
    return nil;
}


- (void)startDownload:(WHC_DownloadSessionTask *)downloadTask {
    if (_downloadSession) {
        NSString * resumeDataFilePath = [self getResumeDataFilePath:downloadTask.saveFileName];
        if (resumeDataFilePath && [_fileManager fileExistsAtPath:resumeDataFilePath]) {
            NSData * resumeData = [NSData dataWithContentsOfFile:resumeDataFilePath];
            downloadTask.downloadTask = [_downloadSession downloadTaskWithResumeData:resumeData];
        }else {
            NSURL * url = [NSURL URLWithString:downloadTask.strUrl];
            NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url];
            downloadTask.downloadTask = [_downloadSession downloadTaskWithRequest:urlRequest];
        }
        [downloadTask startSpeedTimer];
        [downloadTask.downloadTask resume];
        [_downloadTaskArr addObject:downloadTask];
    }
}

- (void)cancelDownloadTask:(BOOL)isDelete task:(WHC_DownloadSessionTask *)task {
    if (!isDelete) {
        [task.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
            // 存储恢复下载数据在didCompleteWithError处理
            NSLog(@"暂停下载");
        }];
    }else {
        [task cancelDownloadTaskAndDeleteFile:isDelete];
    }
}

#pragma mark - 下载过程对外接口

- (nullable WHC_DownloadSessionTask *)downloadOperationWithFileName:(nonnull NSString *)fileName {
    WHC_DownloadSessionTask * downloadTask = nil;
    for (WHC_DownloadSessionTask * tempDownloadTask in _downloadTaskArr) {
        if([tempDownloadTask.saveFileName isEqualToString:fileName]) {
            downloadTask = tempDownloadTask;
            break;
        }
    }
    return downloadTask;
}

- (void)cancelAllDownloadTaskAndDelFile:(BOOL)isDelete {
    for (WHC_DownloadSessionTask * task in _downloadTaskArr) {
        [self cancelDownloadTask:isDelete task:task];
    }
}

- (void)cancelDownloadWithDownloadUrl:(nonnull NSString *)strUrl deleteFile:(BOOL)isDelete {
    for(WHC_DownloadSessionTask * task in _downloadTaskArr){
        if ([task.strUrl isEqualToString:strUrl]) {
            [self cancelDownloadTask:isDelete task:task];
            break;
        }
    }
}

- (void)cancelDownloadWithFileName:(nonnull NSString *)fileName deleteFile:(BOOL)isDelete {
    for(WHC_DownloadSessionTask * task in _downloadTaskArr){
        if([task.saveFileName isEqualToString:fileName]){
            [self cancelDownloadTask:isDelete task:task];
            break;
        }
    }
}

- (WHC_DownloadSessionTask *)replaceCurrentDownloadOperationBlockResponse:(nullable WHCResponse)responseBlock
                                             process:(nullable WHCProgress)processBlock
                                         didFinished:(nullable WHCDidFinished)didFinishedBlock
                                            fileName:(nonnull NSString *)fileName {
    for (WHC_DownloadSessionTask * downloadTask in _downloadTaskArr) {
        if([downloadTask.saveFileName isEqualToString:fileName]){
            downloadTask.delegate = nil;
            downloadTask.progressBlock = processBlock;
            downloadTask.responseBlock = responseBlock;
            downloadTask.didFinishedBlock = didFinishedBlock;
            return downloadTask;
        }
    }
    return nil;
}

- (WHC_DownloadSessionTask *)replaceCurrentDownloadOperationDelegate:(nullable id<WHC_DownloadDelegate>)delegate
                                       fileName:(nonnull NSString *)fileName {
    for (WHC_DownloadSessionTask * downloadTask in _downloadTaskArr) {
        if([downloadTask.saveFileName isEqualToString:fileName]){
            downloadTask.progressBlock = nil;
            downloadTask.responseBlock = nil;
            downloadTask.didFinishedBlock = nil;
            downloadTask.delegate = delegate;
            return downloadTask;
        }
    }
    return nil;
}

- (WHC_DownloadSessionTask *)replaceAllDownloadOperationBlockResponse:(nullable WHCResponse)responseBlock
                                         process:(nullable WHCProgress)processBlock
                                     didFinished:(nullable WHCDidFinished)didFinishedBlock {
    if (_downloadTaskArr.count > 0) {
        for (WHC_DownloadSessionTask * downloadTask in _downloadTaskArr) {
            downloadTask.delegate = nil;
            downloadTask.progressBlock = processBlock;
            downloadTask.responseBlock = responseBlock;
            downloadTask.didFinishedBlock = didFinishedBlock;
        }
        return nil;
    }
    return nil;
}

- (WHC_DownloadSessionTask *)replaceAllDownloadOperationDelegate:(nullable id<WHC_DownloadDelegate>)delegate {
    if (_downloadTaskArr.count > 0) {
        for (WHC_DownloadSessionTask * downloadTask in _downloadTaskArr) {
            downloadTask.progressBlock = nil;
            downloadTask.responseBlock = nil;
            downloadTask.didFinishedBlock = nil;
            downloadTask.delegate = delegate;
        }
        return nil;
    }
    return nil;
}


- (BOOL)existDownloadOperationTaskWithFileName:(nonnull NSString *)fileName {
    BOOL  result = NO;
    for (WHC_DownloadSessionTask * downloadTask in _downloadTaskArr) {
        if([downloadTask.saveFileName isEqualToString:fileName]){
            result = YES;
            break;
        }
    }
    return result;
}

- (BOOL)existDownloadOperationTaskWithUrl:(nonnull NSString *)strUrl {
    BOOL  result = NO;
    for (WHC_DownloadSessionTask * downloadTask in _downloadTaskArr) {
        if([downloadTask.strUrl isEqualToString:strUrl]){
            result = YES;
            break;
        }
    }
    return result;
}


- (WHC_DownloadSessionTask *)getCurrentDownloadTask:(NSURLSessionDownloadTask *)downloadTask {
    WHC_DownloadSessionTask * whc_downloadTask = nil;
    for (WHC_DownloadSessionTask * tempDownloadTask in _downloadTaskArr) {
        if ([tempDownloadTask.downloadTask isEqual:downloadTask]) {
            whc_downloadTask = tempDownloadTask;
            break;
        }
    }
    return whc_downloadTask;
}

- (void)removeDownloadTask:(WHC_DownloadSessionTask *)downloadTask {
    downloadTask.delegate = nil;
    downloadTask.downloadTask = nil;
    downloadTask.responseBlock = nil;
    downloadTask.didFinishedBlock = nil;
    downloadTask.progressBlock = nil;
    [_downloadTaskArr removeObject:downloadTask];
}


- (void)saveDownloadFile:(NSString *)path downloadTask:(WHC_DownloadSessionTask *)downloadTask {
    if (path) {
        if ([_fileManager fileExistsAtPath:downloadTask.saveFilePath isDirectory:NULL]) {
            NSFileHandle * fileHandle = [NSFileHandle fileHandleForWritingAtPath:downloadTask.saveFilePath];
            [fileHandle seekToEndOfFile];
            NSData * data = [NSData dataWithContentsOfFile:path];
            if (data) {
                [fileHandle writeData:data];
                [fileHandle synchronizeFile];
                [fileHandle closeFile];
            }
        }else {
            [_fileManager moveItemAtPath:path toPath:downloadTask.saveFilePath error:NULL];
        }
    }
}

- (void)saveDidFinishDownloadTask:(NSURLSessionDownloadTask *)downloadTask
                            toUrl:(NSURL *)location {
    WHC_DownloadSessionTask * whc_downloadTask = [self getCurrentDownloadTask:downloadTask];
    if (whc_downloadTask) {
        whc_downloadTask.actualFileSizeLenght = downloadTask.countOfBytesExpectedToReceive;
        whc_downloadTask.recvDataLenght = downloadTask.countOfBytesReceived;
        whc_downloadTask.requestStatus = WHCHttpRequestFinished;
        [self saveDownloadFile:location.path downloadTask:whc_downloadTask];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (whc_downloadTask.delegate &&
                [whc_downloadTask.delegate respondsToSelector:@selector(WHCDownloadProgress:recv:total:speed:)]) {
                [whc_downloadTask.delegate WHCDownloadProgress:whc_downloadTask
                                                          recv:downloadTask.countOfBytesReceived
                                                         total:downloadTask.countOfBytesExpectedToReceive
                                                         speed:whc_downloadTask.networkSpeed];
                if ([whc_downloadTask.delegate respondsToSelector:@selector(WHCDownloadDidFinished:data:error:success:)]) {
                    [whc_downloadTask.delegate WHCDownloadDidFinished:whc_downloadTask
                                                                 data:nil
                                                                error:nil
                                                              success:YES];
                }
            }else {
                if (whc_downloadTask.progressBlock) {
                    whc_downloadTask.progressBlock(whc_downloadTask ,
                                                   downloadTask.countOfBytesReceived ,
                                                   downloadTask.countOfBytesExpectedToReceive ,
                                                   whc_downloadTask.networkSpeed);
                }
                if (whc_downloadTask.didFinishedBlock) {
                    whc_downloadTask.didFinishedBlock(whc_downloadTask , nil , nil , YES);
                }
            }
            [self removeDownloadTask:whc_downloadTask];
        });
    }
}

#pragma mark - NSURLSessionDownloadDelegate

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
    
}

- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location {
    [self saveDidFinishDownloadTask:downloadTask toUrl:location];
}

- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error {
    WHC_DownloadSessionTask * whc_downloadTask = [self getCurrentDownloadTask:(NSURLSessionDownloadTask *)task];
    if (whc_downloadTask.delegate &&
        [whc_downloadTask.delegate respondsToSelector:@selector(WHCDownloadDidFinished:data:error:success:)]) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error &&
                [error.userInfo[NSLocalizedDescriptionKey] isEqualToString:@"cancelled"]) {
                NSData * resumeData = error.userInfo[NSURLSessionDownloadTaskResumeData];
                if (resumeData) {
                    [resumeData writeToFile:[self getResumeDataFilePath:whc_downloadTask.saveFileName] atomically:YES];
                }
                if (whc_downloadTask.delegate &&
                    [whc_downloadTask.delegate respondsToSelector:@selector(WHCDownloadDidFinished:data:error:success:)]) {
                    [whc_downloadTask.delegate WHCDownloadDidFinished:whc_downloadTask
                                                                 data:nil
                                                                error:error
                                                              success:NO];
                }else {
                    if (whc_downloadTask.didFinishedBlock) {
                        whc_downloadTask.didFinishedBlock(whc_downloadTask , nil , error , NO);
                    }
                }
                [self removeDownloadTask:whc_downloadTask];
            }
        });
    }
}

- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    WHC_DownloadSessionTask * whc_downloadTask = [self getCurrentDownloadTask:downloadTask];
    whc_downloadTask.recvDataLenght += bytesWritten;
    whc_downloadTask.orderTimeDataLenght += bytesWritten;
    if (whc_downloadTask.actualFileSizeLenght < 10) {
        whc_downloadTask.actualFileSizeLenght = totalBytesExpectedToWrite;
    }
    dispatch_async(dispatch_get_main_queue(), ^{
       if (whc_downloadTask.delegate &&
           [whc_downloadTask.delegate respondsToSelector:@selector(WHCDownloadProgress:recv:total:speed:)]) {
           [whc_downloadTask.delegate WHCDownloadProgress:whc_downloadTask
                                                     recv:totalBytesWritten
                                                    total:totalBytesExpectedToWrite
                                                    speed:whc_downloadTask.networkSpeed];
       }else {
           if (whc_downloadTask.progressBlock) {
               whc_downloadTask.progressBlock(whc_downloadTask ,
                                              totalBytesWritten ,
                                              totalBytesExpectedToWrite ,
                                              whc_downloadTask.networkSpeed);
           }
       }
    });
}

- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes {
    WHC_DownloadSessionTask * whc_downloadTask = [self getCurrentDownloadTask:downloadTask];
    whc_downloadTask.orderTimeDataLenght = fileOffset;
}

- (void)URLSession:(NSURLSession *)session
          dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
    WHC_DownloadSessionTask * whc_downloadTask = [self getCurrentDownloadTask:(NSURLSessionDownloadTask *)dataTask];
    [whc_downloadTask handleResponse:response];
    if (whc_downloadTask.requestStatus == WHCHttpRequestFinished ) {
        [self removeDownloadTask:whc_downloadTask];
    }
}
@end


================================================
FILE: WHCNetWorkKit/Reachability/Reachability.h
================================================
/*
     File: Reachability.h
 Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
  Version: 3.5
 
 Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
 Inc. ("Apple") in consideration of your agreement to the following
 terms, and your use, installation, modification or redistribution of
 this Apple software constitutes acceptance of these terms.  If you do
 not agree with these terms, please do not use, install, modify or
 redistribute this Apple software.
 
 In consideration of your agreement to abide by the following terms, and
 subject to these terms, Apple grants you a personal, non-exclusive
 license, under Apple's copyrights in this original Apple software (the
 "Apple Software"), to use, reproduce, modify and redistribute the Apple
 Software, with or without modifications, in source and/or binary forms;
 provided that if you redistribute the Apple Software in its entirety and
 without modifications, you must retain this notice and the following
 text and disclaimers in all such redistributions of the Apple Software.
 Neither the name, trademarks, service marks or logos of Apple Inc. may
 be used to endorse or promote products derived from the Apple Software
 without specific prior written permission from Apple.  Except as
 expressly stated in this notice, no other rights or licenses, express or
 implied, are granted by Apple herein, including but not limited to any
 patent rights that may be infringed by your derivative works or by other
 works in which the Apple Software may be incorporated.
 
 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
 
 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 
 Copyright (C) 2014 Apple Inc. All Rights Reserved.
 
 */

#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>


typedef enum : NSInteger {
	NotReachable = 0,
	ReachableViaWiFi,
	ReachableViaWWAN
} NetworkStatus;


extern NSString *kReachabilityChangedNotification;


@interface Reachability : NSObject

/*!
 * Use to check the reachability of a given host name.
 */
+ (instancetype)reachabilityWithHostName:(NSString *)hostName;

/*!
 * Use to check the reachability of a given IP address.
 */
+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;

/*!
 * Checks whether the default route is available. Should be used by applications that do not connect to a particular host.
 */
+ (instancetype)reachabilityForInternetConnection;

/*!
 * Checks whether a local WiFi connection is available.
 */
+ (instancetype)reachabilityForLocalWiFi;

/*!
 * Start listening for reachability notifications on the current run loop.
 */
- (BOOL)startNotifier;
- (void)stopNotifier;

- (NetworkStatus)currentReachabilityStatus;

/*!
 * WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand.
 */
- (BOOL)connectionRequired;

@end




================================================
FILE: WHCNetWorkKit/Reachability/Reachability.m
================================================
/*
     File: Reachability.m
 Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
  Version: 3.5
 
 Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
 Inc. ("Apple") in consideration of your agreement to the following
 terms, and your use, installation, modification or redistribution of
 this Apple software constitutes acceptance of these terms.  If you do
 not agree with these terms, please do not use, install, modify or
 redistribute this Apple software.
 
 In consideration of your agreement to abide by the following terms, and
 subject to these terms, Apple grants you a personal, non-exclusive
 license, under Apple's copyrights in this original Apple software (the
 "Apple Software"), to use, reproduce, modify and redistribute the Apple
 Software, with or without modifications, in source and/or binary forms;
 provided that if you redistribute the Apple Software in its entirety and
 without modifications, you must retain this notice and the following
 text and disclaimers in all such redistributions of the Apple Software.
 Neither the name, trademarks, service marks or logos of Apple Inc. may
 be used to endorse or promote products derived from the Apple Software
 without specific prior written permission from Apple.  Except as
 expressly stated in this notice, no other rights or licenses, express or
 implied, are granted by Apple herein, including but not limited to any
 patent rights that may be infringed by your derivative works or by other
 works in which the Apple Software may be incorporated.
 
 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
 
 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 
 Copyright (C) 2014 Apple Inc. All Rights Reserved.
 
 */

#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
#import <sys/socket.h>

#import <CoreFoundation/CoreFoundation.h>

#import "Reachability.h"


NSString *kReachabilityChangedNotification = @"kNetworkReachabilityChangedNotification";


#pragma mark - Supporting functions

#define kShouldPrintReachabilityFlags 1

static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment)
{
#if kShouldPrintReachabilityFlags

    NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
          (flags & kSCNetworkReachabilityFlagsIsWWAN)				? 'W' : '-',
          (flags & kSCNetworkReachabilityFlagsReachable)            ? 'R' : '-',

          (flags & kSCNetworkReachabilityFlagsTransientConnection)  ? 't' : '-',
          (flags & kSCNetworkReachabilityFlagsConnectionRequired)   ? 'c' : '-',
          (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic)  ? 'C' : '-',
          (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
          (flags & kSCNetworkReachabilityFlagsConnectionOnDemand)   ? 'D' : '-',
          (flags & kSCNetworkReachabilityFlagsIsLocalAddress)       ? 'l' : '-',
          (flags & kSCNetworkReachabilityFlagsIsDirect)             ? 'd' : '-',
          comment
          );
#endif
}


static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
{
#pragma unused (target, flags)
	NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
	NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");

    Reachability* noteObject = (__bridge Reachability *)info;
    // Post a notification to notify the client that the network reachability changed.
    [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
}


#pragma mark - Reachability implementation

@implementation Reachability
{
	BOOL _alwaysReturnLocalWiFiStatus; //default is NO
	SCNetworkReachabilityRef _reachabilityRef;
}

+ (instancetype)reachabilityWithHostName:(NSString *)hostName
{
	Reachability* returnValue = NULL;
	SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
	if (reachability != NULL)
	{
		returnValue= [[self alloc] init];
		if (returnValue != NULL)
		{
			returnValue->_reachabilityRef = reachability;
			returnValue->_alwaysReturnLocalWiFiStatus = NO;
		}
	}
	return returnValue;
}


+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress
{
	SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress);

	Reachability* returnValue = NULL;

	if (reachability != NULL)
	{
		returnValue = [[self alloc] init];
		if (returnValue != NULL)
		{
			returnValue->_reachabilityRef = reachability;
			returnValue->_alwaysReturnLocalWiFiStatus = NO;
		}
	}
	return returnValue;
}



+ (instancetype)reachabilityForInternetConnection
{
	struct sockaddr_in zeroAddress;
	bzero(&zeroAddress, sizeof(zeroAddress));
	zeroAddress.sin_len = sizeof(zeroAddress);
	zeroAddress.sin_family = AF_INET;
    
	return [self reachabilityWithAddress:&zeroAddress];
}


+ (instancetype)reachabilityForLocalWiFi
{
	struct sockaddr_in localWifiAddress;
	bzero(&localWifiAddress, sizeof(localWifiAddress));
	localWifiAddress.sin_len = sizeof(localWifiAddress);
	localWifiAddress.sin_family = AF_INET;

	// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0.
	localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);

	Reachability* returnValue = [self reachabilityWithAddress: &localWifiAddress];
	if (returnValue != NULL)
	{
		returnValue->_alwaysReturnLocalWiFiStatus = YES;
	}
    
	return returnValue;
}


#pragma mark - Start and stop notifier

- (BOOL)startNotifier
{
	BOOL returnValue = NO;
	SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};

	if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context))
	{
		if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
		{
			returnValue = YES;
		}
	}
    
	return returnValue;
}


- (void)stopNotifier
{
	if (_reachabilityRef != NULL)
	{
		SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
	}
}


- (void)dealloc
{
	[self stopNotifier];
	if (_reachabilityRef != NULL)
	{
		CFRelease(_reachabilityRef);
	}
}


#pragma mark - Network Flag Handling

- (NetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags
{
	PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
	NetworkStatus returnValue = NotReachable;

	if ((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
	{
		returnValue = ReachableViaWiFi;
	}
    
	return returnValue;
}


- (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
{
	PrintReachabilityFlags(flags, "networkStatusForFlags");
	if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
	{
		// The target host is not reachable.
		return NotReachable;
	}

    NetworkStatus returnValue = NotReachable;

	if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
	{
		/*
         If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi...
         */
		returnValue = ReachableViaWiFi;
	}

	if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
        (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
	{
        /*
         ... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs...
         */

        if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
        {
            /*
             ... and no [user] intervention is needed...
             */
            returnValue = ReachableViaWiFi;
        }
    }

	if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
	{
		/*
         ... but WWAN connections are OK if the calling application is using the CFNetwork APIs.
         */
		returnValue = ReachableViaWWAN;
	}
    
	return returnValue;
}


- (BOOL)connectionRequired
{
	NSAssert(_reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
	SCNetworkReachabilityFlags flags;

	if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
	{
		return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
	}

    return NO;
}


- (NetworkStatus)currentReachabilityStatus
{
	NSAssert(_reachabilityRef != NULL, @"currentNetworkStatus called with NULL SCNetworkReachabilityRef");
	NetworkStatus returnValue = NotReachable;
	SCNetworkReachabilityFlags flags;
    
	if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
	{
		if (_alwaysReturnLocalWiFiStatus)
		{
			returnValue = [self localWiFiStatusForFlags:flags];
		}
		else
		{
			returnValue = [self networkStatusForFlags:flags];
		}
	}
    
	return returnValue;
}


@end


================================================
FILE: WHCNetWorkKit/UIKit+WHCNetWorkKit/UIButton+WHC_HttpButton.h
================================================
//
//  UIButton+WHC_HttpButton.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//
/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */
#import <UIKit/UIKit.h>

@interface UIButton (WHC_HttpButton)

/**
 * 说明: 给按钮设置网络图片 (没有默认图片)
 * @param strUrl 图片地址
 * @param state 图片对应的状态
 */

- (void)whc_setImageWithUrl:(nonnull NSString *)strUrl
                   forState:(UIControlState)state;

/**
 * 说明: 给按钮设置网络图片
 * @param strUrl 图片地址
 * @param state 图片对应的状态
 * @param placeholderImage 默认显示图片
 */

- (void)whc_setImageWithUrl:(nonnull NSString *)strUrl
                   forState:(UIControlState)state
           placeholderImage:(nullable UIImage *)image;


/**
 * 说明: 给按钮背景设置网络图片
 * @param strUrl 图片地址
 * @param state 图片对应的状态
 */

- (void)whc_setBackgroundImageWithURL:(nonnull NSString *)strUrl
                             forState:(UIControlState)state;

/**
 * 说明: 给按钮背景设置网络图片
 * @param strUrl 图片地址
 * @param state 图片对应的状态
 * @param placeholderImage 默认显示图片
 */

- (void)whc_setBackgroundImageWithURL:(nonnull NSString *)strUrl
                             forState:(UIControlState)state
                     placeholderImage:(nullable UIImage *)image;

@end


================================================
FILE: WHCNetWorkKit/UIKit+WHCNetWorkKit/UIButton+WHC_HttpButton.m
================================================
//
//  UIButton+WHC_HttpButton.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//
/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */
#import "UIButton+WHC_HttpButton.h"
#import <objc/runtime.h>
#import "WHC_ImageCache.h"
#import "WHC_HttpManager.h"


@implementation UIButton (WHC_HttpButton)

- (NSMutableDictionary *)operationDictionary {
    NSMutableDictionary *operationDictionary = objc_getAssociatedObject([WHC_ImageCache shared], &loadOperationKey);
    if (!operationDictionary) {
        operationDictionary = [NSMutableDictionary dictionary];
        objc_setAssociatedObject([WHC_ImageCache shared],
                                 &loadOperationKey,
                                 operationDictionary,
                                 OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return operationDictionary;
}

- (void)cancelOperationWithState:(UIControlState)state url:(NSString *)strUrl {
    NSMutableDictionary * operationDict = [self operationDictionary];
    WHC_BaseOperation * operation = [operationDict objectForKey:@(state).stringValue];
    if (operation) {
        if ([operation.strUrl isEqualToString:strUrl]){
            [[WHC_ImageCache shared].callBackDictionary removeObjectForKey:strUrl];
        }
        [operation cancelledRequest];
        [operationDict removeObjectForKey:@(state).stringValue];
    }
}

- (void)addOperation:(WHC_BaseOperation *)operation forState:(UIControlState)state {
    if (operation) {
        NSMutableDictionary * operationDict = [self operationDictionary];
        [operationDict setValue:operation forKey:@(state).stringValue];
    }
}

- (void)removeOperationForState:(UIControlState)state url:(NSString *)strUrl{
    NSMutableDictionary * operationDict = [self operationDictionary];
    [operationDict removeObjectForKey:@(state).stringValue];
    if ([operationDict.allKeys containsObject:@(state).stringValue]) {
        [[WHC_ImageCache shared].callBackDictionary removeObjectForKey:strUrl];
    }
}

- (void)whc_setImageWithUrl:(nonnull NSString *)strUrl
                   forState:(UIControlState)state {
    [self whc_setImageWithUrl:strUrl
                     forState:state placeholderImage:nil];
}

- (void)whc_setImageWithUrl:(nonnull NSString *)strUrl
                   forState:(UIControlState)state
           placeholderImage:(nullable UIImage *)image {
    if (!strUrl && !image){
        return;
    }
    [self cancelOperationWithState:state url:strUrl];
    if (image) {
        [self setImage:image forState:state];
    }
    if (![[WHC_HttpManager shared].failedUrls containsObject:strUrl]){
        __weak typeof(self) weakSelf = self;
        [[WHC_ImageCache shared]queryImageForUrl:strUrl state:state didFinished:^(UIImage *image , UIControlState state) {
            if (!image) {
                if (![WHC_ImageCache shared].callBackDictionary[strUrl]) {
                    [WHC_ImageCache shared].callBackDictionary[strUrl] = [NSMutableArray array];
                   WHC_BaseOperation * operation = [[WHC_HttpManager shared] get:strUrl didFinished: ^(WHC_BaseOperation *operation, NSData *data, NSError *error, BOOL isSuccess) {
                             if (!isSuccess) {
                                 if (operation) {
                                     [[WHC_ImageCache shared].callBackDictionary removeObjectForKey:operation.strUrl];
                                 }
                             }else {
                                 UIImage * image = [UIImage imageWithData:data];
                                 [weakSelf setImage:image forState:state];
                                 [[WHC_ImageCache shared] storeImage:image forUrl:operation.strUrl];
                                 NSMutableArray * urlCallBackArr = [[WHC_ImageCache shared].callBackDictionary[operation.strUrl] copy];
                                 [[WHC_ImageCache shared].callBackDictionary removeObjectForKey:operation.strUrl];
                                 typedef  void (^callBack)(UIImage * image);
                                 for (NSMutableDictionary * dict in urlCallBackArr) {
                                     callBack cb = dict[@"completed"];
                                     cb(image);
                                 }
                             }
                         }];
                    [weakSelf addOperation:operation forState:state];
                }
                NSMutableArray *callbacksForURL = [WHC_ImageCache shared].callBackDictionary[strUrl];
                NSMutableDictionary *callbacks = [NSMutableDictionary dictionary];
                callbacks[@"completed"] = ^(UIImage * image){
                    [weakSelf setImage:image forState:state];
                };
                [callbacksForURL addObject:callbacks];
                [WHC_ImageCache shared].callBackDictionary[strUrl] = callbacksForURL;
            }else {
                [self setImage:image forState:state];
            }
        }];
    }
}


- (void)whc_setBackgroundImageWithURL:(nonnull NSString *)strUrl
                             forState:(UIControlState)state {
    [self whc_setBackgroundImageWithURL:strUrl
                               forState:state placeholderImage:nil];
}

- (void)whc_setBackgroundImageWithURL:(nonnull NSString *)strUrl
                             forState:(UIControlState)state
                     placeholderImage:(nullable UIImage *)image {
    if (!strUrl && !image){
        return;
    }
    [self cancelOperationWithState:state url:strUrl];
    if (image) {
        [self setBackgroundImage:image forState:state];
    }
    if (![[WHC_HttpManager shared].failedUrls containsObject:strUrl]){
        __weak typeof(self) weakSelf = self;
        [[WHC_ImageCache shared]queryImageForUrl:strUrl state:state didFinished:^(UIImage *image , UIControlState state) {
            if (!image) {
                if (![WHC_ImageCache shared].callBackDictionary[strUrl]) {
                    [WHC_ImageCache shared].callBackDictionary[strUrl] = [NSMutableArray array];
                    WHC_BaseOperation * operation = [[WHC_HttpManager shared] get:strUrl didFinished: ^(WHC_BaseOperation *operation, NSData *data, NSError *error, BOOL isSuccess) {
                        if (!isSuccess) {
                            if (operation) {
                                [[WHC_ImageCache shared].callBackDictionary removeObjectForKey:operation.strUrl];
                            }
                        }else {
                            UIImage * image = [UIImage imageWithData:data];
                            [weakSelf setBackgroundImage:image forState:state];
                            [[WHC_ImageCache shared] storeImage:image forUrl:operation.strUrl];
                            NSMutableArray * urlCallBackArr = [[WHC_ImageCache shared].callBackDictionary[operation.strUrl] copy];
                            [[WHC_ImageCache shared].callBackDictionary removeObjectForKey:operation.strUrl];
                            typedef  void (^callBack)(UIImage * image);
                            for (NSMutableDictionary * dict in urlCallBackArr) {
                                callBack cb = dict[@"completed"];
                                cb(image);
                            }
                        }
                    }];
                    [weakSelf addOperation:operation forState:state];
                }
                NSMutableArray *callbacksForURL = [WHC_ImageCache shared].callBackDictionary[strUrl];
                NSMutableDictionary *callbacks = [NSMutableDictionary dictionary];
                callbacks[@"completed"] = ^(UIImage * image){
                    [weakSelf setBackgroundImage:image forState:state];
                };
                [callbacksForURL addObject:callbacks];
                [WHC_ImageCache shared].callBackDictionary[strUrl] = callbacksForURL;
            }else {
                [weakSelf setBackgroundImage:image forState:state];
            }
        }];
    }
}


@end


================================================
FILE: WHCNetWorkKit/UIKit+WHCNetWorkKit/UIImageView+WHC_HttpImageView.h
================================================
//
//  UIImageView+WHC_HttpImageView.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//
/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */
#import <UIKit/UIKit.h>

@interface UIImageView (WHC_HttpImageView)

/**
 * 说明: 给UIImageView背景设置网络图片
 * @param strUrl 图片地址
 */

- (void)whc_setImageWithUrl:(nonnull NSString *)strUrl ;

/**
 * 说明: 给UIImageView背景设置网络图片
 * @param strUrl 图片地址
 * @param placeholderImage 默认显示图片
 */

- (void)whc_setImageWithUrl:(nonnull NSString *)strUrl placeholderImage:(nullable UIImage *)image;

/**
 * 说明: 给UIImageView 设置本地git图片
 * @param path gif本地路径
 */
- (void)setGifWithPath:(nonnull NSString *)path;

@end


================================================
FILE: WHCNetWorkKit/UIKit+WHCNetWorkKit/UIImageView+WHC_HttpImageView.m
================================================
//
//  UIImageView+WHC_HttpImageView.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//
/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */
#import "UIImageView+WHC_HttpImageView.h"
#import <objc/runtime.h>
#import "WHC_ImageCache.h"
#import "WHC_HttpManager.h"
#import <ImageIO/ImageIO.h>

@implementation UIImageView (WHC_HttpImageView)

- (NSMutableDictionary *)operationDictionary {
    NSMutableDictionary *operationDictionary = objc_getAssociatedObject([WHC_ImageCache shared], &loadOperationKey);
    if (!operationDictionary) {
        operationDictionary = [NSMutableDictionary dictionary];
        objc_setAssociatedObject([WHC_ImageCache shared], &loadOperationKey, operationDictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return operationDictionary;
}

- (void)cancelOperationWithUrl:(NSString *)strUrl {
    NSMutableDictionary * operationDictionary = [self operationDictionary];
    WHC_BaseOperation * operation = [operationDictionary objectForKey:strUrl];
    if (operation) {
        [[WHC_ImageCache shared].callBackDictionary removeObjectForKey:strUrl];
        [operation cancelledRequest];
        [operationDictionary removeObjectForKey:strUrl];
    }
}

- (void)addOperation:(WHC_BaseOperation *)operation url:(NSString *)strUrl{
    if (operation) {
        NSMutableDictionary * operationDict = [self operationDictionary];
        [operationDict setValue:operation forKey:strUrl];
    }
}

- (void)removeOperationForUrl:(NSString *)strUrl{
    NSMutableDictionary * operationDict = [self operationDictionary];
    [operationDict removeObjectForKey:strUrl];
    [[WHC_ImageCache shared].callBackDictionary removeObjectForKey:strUrl];
}

- (void)whc_setImageWithUrl:(nonnull NSString *)strUrl {
    [self whc_setImageWithUrl:strUrl placeholderImage:nil];
}

- (void)whc_setImageWithUrl:(nonnull NSString *)strUrl placeholderImage:(nullable UIImage *)image {
    if (!strUrl && !image){
        return;
    }
    [self cancelOperationWithUrl:strUrl];
    if (image) {
        [self setImage:image];
    }
    if (![[WHC_HttpManager shared].failedUrls containsObject:strUrl]){
        __weak typeof(self) weakSelf = self;
        [[WHC_ImageCache shared]queryImageForUrl:strUrl
                                           state:UIControlStateNormal
                                     didFinished:^(UIImage *image , UIControlState state) {
            if (!image) {
                if (![WHC_ImageCache shared].callBackDictionary[strUrl]) {
                    [WHC_ImageCache shared].callBackDictionary[strUrl] = [NSMutableArray array];
                    WHC_BaseOperation * operation = [[WHC_HttpManager shared] get:strUrl didFinished: ^(WHC_BaseOperation *operation, NSData *data, NSError *error, BOOL isSuccess) {
                        if (!isSuccess) {
                            if (operation) {
                                [[WHC_ImageCache shared].callBackDictionary removeObjectForKey:operation.strUrl];
                            }
                        }else {
                            UIImage * image = nil;
                            if ([[[WHC_HttpManager shared] fileFormatWithUrl:operation.strUrl] isEqualToString:@".gif"]) {
                                image = [self gifImageWithData:data];
                            }else {
                                image = [UIImage imageWithData:data];
                            }
                            [weakSelf setImage:image];
                            [[WHC_ImageCache shared] storeImage:image forUrl:operation.strUrl];
                            NSMutableArray * urlCallBackArr = [[WHC_ImageCache shared].callBackDictionary[operation.strUrl] copy];
                            [[WHC_ImageCache shared].callBackDictionary removeObjectForKey:operation.strUrl];
                            typedef  void (^callBack)(UIImage * image);
                            for (NSMutableDictionary * dict in urlCallBackArr) {
                                callBack cb = dict[@"completed"];
                                cb(image);
                            }
                        }
                    }];
                    [weakSelf addOperation:operation url:strUrl];
                }
                NSMutableArray *callbacksForURL = [WHC_ImageCache shared].callBackDictionary[strUrl];
                NSMutableDictionary *callbacks = [NSMutableDictionary dictionary];
                callbacks[@"completed"] = ^(UIImage * image){
                    [weakSelf setImage:image];
                };
                [callbacksForURL addObject:callbacks];
                [WHC_ImageCache shared].callBackDictionary[strUrl] = callbacksForURL;
            }else {
                [self setImage:image];
            }
        }];
    }
}

- (void)setGifWithPath:(nonnull NSString *)path {
    NSData *data = [NSData dataWithContentsOfFile:path];
    self.image = [self gifImageWithData:data];
}

- (UIImage *)gifImageWithData:(NSData *)gifData{
    NSMutableArray  * imageArr = [NSMutableArray array];
    CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef) gifData, NULL);
    NSTimeInterval animationDuration = 0.0;
    if (src) {
        NSUInteger frameCount = CGImageSourceGetCount(src);
        NSDictionary *gifProperties = (NSDictionary *) CFBridgingRelease(CGImageSourceCopyProperties(src, NULL));
        if(gifProperties) {
            NSDictionary *gifDictionary =[gifProperties objectForKey:(NSString*)kCGImagePropertyGIFDictionary];
            NSUInteger loopCount = [[gifDictionary objectForKey:(NSString*)kCGImagePropertyGIFLoopCount] integerValue];
            self.animationRepeatCount = loopCount;
            for (NSUInteger i = 0; i < frameCount; i++) {
                CGImageRef img = CGImageSourceCreateImageAtIndex(src, (size_t) i, NULL);
                if (img) {
                    UIImage *frameImage = [UIImage imageWithCGImage:img];
                    if(frameImage){
                        [imageArr addObject:frameImage];
                    }
                    NSDictionary *frameProperties = (NSDictionary *) CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(src, (size_t) i, NULL));
                    if (frameProperties) {
                        NSDictionary *frameDictionary = [frameProperties objectForKey:(NSString*)kCGImagePropertyGIFDictionary];
                        CGFloat delayTime = [[frameDictionary objectForKey:(NSString*)kCGImagePropertyGIFDelayTime] floatValue];
                        animationDuration += delayTime;
                    }
                    CGImageRelease(img);
                }
            }
        }
        CFRelease(src);
    }
    return [UIImage animatedImageWithImages:imageArr duration:animationDuration];
}

@end


================================================
FILE: WHCNetWorkKit/UIKit+WHCNetWorkKit/WHC_ImageCache.h
================================================
//
//  WHC_ImageCache.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//
/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

/**
 * 读取当前图片下载操作key
 */

static char loadOperationKey;

/**
 * 查询本地磁盘缓存和内存缓存结束回调块
 * @param: image 查询获取的图片对象
 * @param: state 图片显示对应的状态(这个只针对UIButton)
 */

typedef void(^WHCImageQueryFinished)(UIImage * _Nullable image , UIControlState state);

/**
 * 说明: WHC_ImageCache 网络下载图片缓存类
 */

@interface WHC_ImageCache : NSObject

/**
 * 说明: WHC_ImageCache 单例对象
 */

+ (nonnull instancetype)shared;

/**
 * 网络请求404错误集合(下次再遇到则不请求)
 */

@property (nonatomic , strong , nonnull) NSMutableSet * failedUrls;

/**
 * 异步图片下载回调块字典集合
 */

@property (nonatomic , strong , nonnull) NSMutableDictionary * callBackDictionary;

/**
 * 正在进行异步图片下载操作对象数组集合
 */

@property (nonatomic , strong , nonnull) NSMutableArray * runningOperationArray;

/**
 * 存储图片对象
 * @param: image 图片对象
 * @param: strUrl 图片下载地址
 */

- (void)storeImage:(nonnull UIImage *)image
            forUrl:(nonnull NSString *)strUrl;

/**
 * 查询本地磁盘缓存和内存缓存图片(异步查询)
 * @param: strUrl 图片下载地址
 * @param: state 图片对应得按钮状态(这个只针对UIButton)
 * @param: finishedBlock 查询完成回调块
 */

- (void)queryImageForUrl:(nonnull NSString *)strUrl
                   state:(UIControlState)state
             didFinished:(nullable WHCImageQueryFinished)finishedBlock;
@end


================================================
FILE: WHCNetWorkKit/UIKit+WHCNetWorkKit/WHC_ImageCache.m
================================================
//
//  WHC_ImageCache.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/11/6.
//  Copyright © 2015年 吴海超. All rights reserved.
//
/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */
#import "WHC_ImageCache.h"
#import <CommonCrypto/CommonDigest.h>
#import "WHC_HttpManager.h"
#import <objc/runtime.h>

#define kWHCImageCachePath (@"WHCImageCache")



@interface WHC_Cache : NSCache

@end

@implementation WHC_Cache

- (id)init {
    self = [super init];
    if (self) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(removeAllObjects) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
    }
    return self;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIApplicationDidReceiveMemoryWarningNotification
                                                  object:nil];
}

@end

@interface WHC_ImageCache (){
    NSFileManager  * _fileManager;
    dispatch_queue_t _fileQueue;
}
@property (nonatomic , strong) WHC_Cache * memCache;
@property (nonatomic , strong) NSString * diskCachePath;

@end

static inline NSUInteger WHCCacheCostForImage(UIImage *image) {
    return image.size.height * image.size.width * image.scale * image.scale;
}

@implementation WHC_ImageCache

+ (nonnull instancetype)shared {
    static WHC_ImageCache * imageCache;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        imageCache = [WHC_ImageCache new];
    });
    return imageCache;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _callBackDictionary = [NSMutableDictionary dictionary];
        _runningOperationArray = [NSMutableArray array];
        _fileQueue = dispatch_queue_create([NSStringFromClass(self.class) UTF8String], NULL);
        _failedUrls = [NSMutableSet set];
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        _diskCachePath = [paths[0] stringByAppendingPathComponent:kWHCImageCachePath];
        
        _memCache = [WHC_Cache new];
        _memCache.name = kWHCImageCachePath;
        
        dispatch_sync(_fileQueue, ^{
            _fileManager = [NSFileManager new];
            if (![_fileManager fileExistsAtPath:_diskCachePath]) {
                [_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
            }
        });
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(clearMemory)
                                                     name:UIApplicationDidReceiveMemoryWarningNotification
                                                   object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(cleanDisk)
                                                     name:UIApplicationWillTerminateNotification
                                                   object:nil];
    }
    return self;
}

- (NSString *)cachedImageFileNameForUrl:(NSString *)strUrl {
    NSMutableString * cachedFileName = [NSMutableString string];
    if (strUrl != nil) {
        const char * cStr = strUrl.UTF8String;
        unsigned char buffer[CC_MD5_DIGEST_LENGTH];
        memset(buffer, 0x00, CC_MD5_DIGEST_LENGTH);
        CC_MD5(cStr, (CC_LONG)(strlen(cStr)), buffer);
        for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
            [cachedFileName appendFormat:@"%02x",buffer[i]];
        }
        return cachedFileName;
    }
    return nil;
}

- (UIImage *)diskImageForUrl:(NSString *)strUrl {
    NSString * filePath = [_diskCachePath stringByAppendingPathComponent:[self cachedImageFileNameForUrl:strUrl]];
    BOOL isDirectory = NO;
    if ([_fileManager fileExistsAtPath:filePath isDirectory:&isDirectory]) {
        NSData * imageData = [NSData dataWithContentsOfFile:filePath];
        if (imageData){
            return [UIImage imageWithData:imageData];
        }else {
            return nil;
        }
    }
    return nil;
}

- (void)storeImage:(UIImage *)image forUrl:(NSString *)strUrl {
    if (!image || !strUrl){
        return;
    }
    [self.memCache setObject:image forKey:strUrl cost:WHCCacheCostForImage(image)];
    dispatch_async(_fileQueue, ^{
        NSString * filePath = [_diskCachePath stringByAppendingPathComponent:[self cachedImageFileNameForUrl:strUrl]];
        NSString * imageFormat = [[WHC_HttpManager shared] fileFormatWithUrl:strUrl];
        NSData * imageData = nil;
        if ([imageFormat isEqualToString:@".png"]) {
            imageData = UIImagePNGRepresentation(image);
        }else {
            imageData = UIImageJPEGRepresentation(image, 1.0);
        }
        [_fileManager createFileAtPath:filePath contents:imageData attributes:NULL];
    });
}

- (void)queryImageForUrl:(NSString *)strUrl state:(UIControlState)state didFinished:(WHCImageQueryFinished)finishedBlock {
    if (!finishedBlock) {
        return;
    }
    if (!strUrl) {
        finishedBlock(nil , state);
        return;
    }
    
    UIImage * image = [self.memCache objectForKey:strUrl];
    if (image) {
        finishedBlock(image , state);
    }else {
        dispatch_async(_fileQueue, ^{
            @autoreleasepool {
                UIImage *diskImage = [self diskImageForUrl:strUrl];
                if (diskImage) {
                    [self.memCache setObject:diskImage forKey:strUrl cost:WHCCacheCostForImage(diskImage)];
                }
                dispatch_async(dispatch_get_main_queue(), ^{
                    finishedBlock(diskImage , state);
                });
            }
        });
    }
}

- (void)clearMemory {
    [self.memCache removeAllObjects];
}

- (void)cleanDisk {
    dispatch_async(_fileQueue, ^{
        [_fileManager removeItemAtPath:_diskCachePath error:nil];
        [_fileManager createDirectoryAtPath:self.diskCachePath
                withIntermediateDirectories:YES
                                 attributes:nil
                                      error:NULL];
    });
}
@end


================================================
FILE: WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_DataModel.h
================================================
//
//  WHC_DataModel.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/4/29.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import <Foundation/Foundation.h>

/**
 * 说明: WHC_DataModel json/xml转模型类对象
 */

@interface WHC_DataModel : NSObject

/**
 * 说明: json/xml (data)数据对象转模型类对象数组
 * @param: data json/xml数据对象
 * @param: className 模型类
 */

+ (NSArray *)dataModelWithArrayData:(NSData *)data className:(Class)className;

/**
 * 说明: json/xml (array)数组对象转模型类对象数组
 * @param: array json/xml数组对象
 * @param: className 模型类
 */

+ (NSArray*)dataModelWithArray:(NSArray*)array className:(Class)className;

/**
 * 说明: json/xml (dictionary)字典对象转模型类对象
 * @param: data json/xml字典对象
 * @param: className 模型类
 */

+ (id)dataModelWithDictionary:(NSDictionary*)dictionary className:(Class)className;

/**
 * 说明: json/xml (data)字典对象转模型类对象
 * @param: data json/xml字典对象
 * @param: className 模型类
 */

+ (id)dataModelWithDictionaryData:(NSData *)data className:(Class)className;

@end


================================================
FILE: WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_DataModel.m
================================================
//
//  WHC_DataModel.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/4/29.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import "WHC_DataModel.h"
#import <objc/runtime.h>
#define kWHCKey    (@"")
@interface WHC_DataModel (){
    
}

@end
@implementation WHC_DataModel

- (instancetype)init{
    self = [super init];
    if(self){
    
    }
    return self;
}

+ (NSArray *)dataModelWithArrayData:(NSData *)data className:(Class)className{
    NSArray * array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
    return [WHC_DataModel dataModelWithArray:array className:className];
}

+ (NSArray*)dataModelWithArray:(NSArray*)array className:(Class)className{
    NSMutableArray * _array = [NSMutableArray new];
    for (NSDictionary * dict in array) {
        [_array addObject:[WHC_DataModel dataModelWithDictionary:dict className:className]];
    }
    return _array;
}

+ (id)dataModelWithDictionary:(NSDictionary*)dictionary className:(Class)className{
    WHC_DataModel  * whcDataModel = [WHC_DataModel new];
    id object = [whcDataModel handleDataModelEngine:dictionary arrKey:kWHCKey calssName:className];
    return object;
}

+ (id)dataModelWithDictionaryData:(NSData *)data className:(Class)className{
    NSDictionary * dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
    return [WHC_DataModel dataModelWithDictionary:dict className:className];
}

- (NSString *)getClassNameString:(const char *)attr{
    NSString * strClassName = nil;
    NSString * attrStr = @(attr);
    NSRange  oneRange = [attrStr rangeOfString:@"T@\""];
    if(oneRange.location != NSNotFound){
        NSRange twoRange = [attrStr rangeOfString:@"\"" options:NSBackwardsSearch];
        if(twoRange.location != NSNotFound){
            NSRange  classRange = NSMakeRange(oneRange.location + oneRange.length, twoRange.location - (oneRange.location + oneRange.length));
            strClassName = [attrStr substringWithRange:classRange];
        }
    }
    return strClassName;
}

- (BOOL)existproperty:(NSString *)property withObject:(NSObject *)object{
    unsigned int  propertyCount = 0;
    Ivar *vars = class_copyIvarList([object class], &propertyCount);
    for (NSInteger i = 0; i < propertyCount; i++) {
        Ivar var = vars[i];
        NSString * tempProperty = [[NSString stringWithUTF8String:ivar_getName(var)] stringByReplacingOccurrencesOfString:@"_" withString:@""];
        if([property isEqualToString:tempProperty]){
            return YES;
        }
    }
    return NO;
}

- (Class)classExistProperty:(NSString *)property withObject:(NSObject *)object{
    Class  class = [NSNull class];
    unsigned int  propertyCount = 0;
    Ivar *vars = class_copyIvarList([object class], &propertyCount);
    for (NSInteger i = 0; i < propertyCount; i++) {
        Ivar var = vars[i];
        NSString * tempProperty = [[NSString stringWithUTF8String:ivar_getName(var)] stringByReplacingOccurrencesOfString:@"_" withString:@""];
        if([property isEqualToString:tempProperty]){
            NSString * type = [NSString stringWithUTF8String:ivar_getTypeEncoding(var)];
            if([type hasPrefix:@"@"]){
                type = [type stringByReplacingOccurrencesOfString:@"@" withString:@""];
                type = [type stringByReplacingOccurrencesOfString:@"\"" withString:@""];
                class = NSClassFromString(type);
            }
        }
    }
    return class;
}

- (id)handleDataModelEngine:(id)object arrKey:(NSString*)arrKey calssName:(Class)className{
    if(object){
        id  modelObject = [className new];
        if([object isKindOfClass:[NSDictionary class]]){
            NSDictionary  * dict = object;
            NSInteger       count = dict.count;
            NSArray       * keyArr = [dict allKeys];
            for (NSInteger i = 0; i < count; i++) {
                id subObject = dict[keyArr[i]];
                if(subObject){
                    if([self classExistProperty:keyArr[i] withObject:modelObject] == [NSDictionary class]){
                        if([subObject isKindOfClass:[NSNull class]]){
                            [modelObject setValue:@{} forKey:keyArr[i]];
                        }else{
                            id subModelObject = [self handleDataModelEngine:subObject arrKey:keyArr[i] calssName:objc_getClass([keyArr[i] UTF8String])];
                            [modelObject setValue:subModelObject forKey:keyArr[i]];
                        }
                    }else if ([self classExistProperty:keyArr[i] withObject:modelObject] == [NSArray class]){
                        if([subObject isKindOfClass:[NSNull class]]){
                            [modelObject setValue:@[] forKey:keyArr[i]];
                        }else{
                            id subModelObject = [self handleDataModelEngine:subObject arrKey:keyArr[i] calssName:objc_getClass([keyArr[i] UTF8String])];
                            [modelObject setValue:[subModelObject mutableCopy] forKey:keyArr[i]];
                        }
                    }else if ([self classExistProperty:keyArr[i] withObject:modelObject] == [NSString class]){
                        if([subObject isKindOfClass:[NSNull class]]){
                            [modelObject setValue:@"" forKey:keyArr[i]];
                        }else{
                            [modelObject setValue:subObject forKey:keyArr[i]];
                        }
                    }else if ([self classExistProperty:keyArr[i] withObject:modelObject] == [NSNumber class]){
                        if([subObject isKindOfClass:[NSNull class]]){
                            [modelObject setValue:@(0) forKey:keyArr[i]];
                        }else{
                            [modelObject setValue:subObject forKey:keyArr[i]];
                        }
                    }else{
                        if(subObject && ![subObject isKindOfClass:[NSNull class]]){
                            id subModelObject = [self handleDataModelEngine:subObject arrKey:keyArr[i] calssName:objc_getClass([keyArr[i] UTF8String])];
                            if([self existproperty:keyArr[i] withObject:modelObject]){
                                [modelObject setValue:subModelObject forKey:keyArr[i]];
                            }
                        }else{
                            if([self existproperty:keyArr[i] withObject:modelObject]){
                                [modelObject setValue:@"" forKey:keyArr[i]];
                            }
                        }
                    }
                }
            }
        }else if ([object isKindOfClass:[NSArray class]]){
            NSArray  * objectArr = object;
            NSInteger  count = objectArr.count;
            NSMutableArray  * modelObjectArr = [NSMutableArray new];
            for (NSInteger i = 0; i < count; i++) {
                id subModelObject = [self handleDataModelEngine:objectArr[i] arrKey:arrKey calssName:objc_getClass([arrKey UTF8String])];
                if(subModelObject){
                    [modelObjectArr addObject:subModelObject];
                }
            }
            modelObject = nil;
            return modelObjectArr;
        }else if([object isKindOfClass:[NSString class]]){
            if(object){
                return object;
            }else{
                return @"";
            }
        }else if([object isKindOfClass:[NSNumber class]]){
            if(object){
                return object;
            }else{
                return @(0);
            }
        }else{
            unsigned int propertyCount = 0;
            objc_property_t  * propertys = class_copyPropertyList(className, &propertyCount);
            for (int i = 0; i < propertyCount; i++) {
                NSString * propertyName = @(property_getName(propertys[i]));
                NSString * classType = [self getClassNameString:property_getAttributes(propertys[i])];
                if(classType){
                    Class propertyClass = objc_getClass([classType UTF8String]);
                    if(propertyClass == [NSDictionary class]){
                        id subObject = [object objectForKey:propertyName];
                        if([subObject isKindOfClass:[NSNull class]]){
                            [modelObject setValue:@{} forKey:propertyName];
                        }else{
                            id subModelObject = [self handleDataModelEngine:subObject arrKey:propertyName calssName:objc_getClass([propertyName UTF8String])];
                            [modelObject setValue:subModelObject forKey:propertyName];
                        }
                    }else if (propertyClass == [NSArray class]){
                        id subObject = [object objectForKey:propertyName];
                        if([subObject isKindOfClass:[NSNull class]]){
                            [modelObject setValue:@[] forKey:propertyName];
                        }else{
                            id subModelObject = [self handleDataModelEngine:subObject arrKey:propertyName calssName:objc_getClass([arrKey UTF8String])];
                            [modelObject setValue:subModelObject forKey:propertyName];
                        }
                    }else if(propertyClass == [NSString class] ||
                             propertyClass == [NSNumber class]){
                        id value = [object objectForKey:propertyName];
                        if(value && ![value isKindOfClass:[NSNull class]]){
                            [modelObject setValue:value forKey:propertyName];
                        }else{
                            if([value isKindOfClass:[NSString class]]){
                                [modelObject setValue:@"" forKey:propertyName];
                            }else{
                                [modelObject setValue:@(0) forKey:propertyName];
                            }
                        }
                    }else if (propertyClass == objc_getClass([propertyName UTF8String])){
                        id subObject = [object objectForKey:propertyName];
                        if(subObject && ![subObject isKindOfClass:[NSNull class]]){
                            id subModelObject = [self handleDataModelEngine:subObject arrKey:propertyName calssName:objc_getClass([propertyName UTF8String])];
                           [modelObject setValue:subModelObject forKey:propertyName];
                        }else{
                            [modelObject setValue:[objc_getClass([propertyName UTF8String]) new] forKey:propertyName];
                        }
                    }
                }
            }
        }
        return modelObject;
    }else{
        NSLog(@"有object = nil");
    }
    return nil;
}
@end


================================================
FILE: WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_Json.h
================================================
//
//  WHC_Json.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/4/29.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import <Foundation/Foundation.h>

/**
 * 说明: WHC_Json dictionary对象转换为json字符串
 */

@interface WHC_Json : NSObject


/**
 * 说明: dictionary对象转换为json字符串
 */
+ (NSString *)jsonWithDictionary:(NSDictionary*)dictionary;

/**
 * 说明: jsonData对象转换为NSDictionary对象
 */
+ (NSDictionary *)dictionaryWithJsonData:(NSData *)jsonData;

/**
 * 说明: json字符串对象转换为NSDictionary对象
 */
+ (NSDictionary *)dictionaryWithJson:(NSString *)json;

/**
 * 说明: jsonData对象转换为NSArray对象
 */
+ (NSArray *)arrayWithJsonData:(NSData *)jsonData;

/**
 * 说明: json字符串对象转换为NSArray对象
 */
+ (NSArray *)arrayWithJson:(NSString *)json;

@end


================================================
FILE: WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_Json.m
================================================
//
//  WHC_Json.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/4/29.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import "WHC_Json.h"

@interface WHC_Json (){
    NSMutableString            * _jsonString;     //存放json字符串
}

@end

@implementation WHC_Json

- (instancetype)init{
    self = [super init];
    if(self){
        _jsonString  = [NSMutableString new];
        [_jsonString appendString:@"{"];
    }
    return self;
}

+ (NSString*)jsonWithDictionary:(NSDictionary *)dictionary{
    assert(dictionary);
    WHC_Json  * whcJson = [WHC_Json new];
    return [NSString stringWithFormat:@"%@}",[whcJson handleDictionaryEngine:dictionary]];
}

+ (NSDictionary *)dictionaryWithJsonData:(NSData *)jsonData {
    assert(jsonData);
    return [NSJSONSerialization JSONObjectWithData:jsonData
                                           options:NSJSONReadingAllowFragments error:nil];
}

+ (NSDictionary *)dictionaryWithJson:(NSString *)json {
    assert(json);
    return [WHC_Json dictionaryWithJsonData:[json dataUsingEncoding:NSUTF8StringEncoding]];
}

+ (NSArray *)arrayWithJsonData:(NSData *)jsonData {
    assert(jsonData);
    return [NSJSONSerialization JSONObjectWithData:jsonData
                                           options:NSJSONReadingAllowFragments error:nil];
}

+ (NSArray *)arrayWithJson:(NSString *)json {
    assert(json);
    return [WHC_Json arrayWithJsonData:[json dataUsingEncoding:NSUTF8StringEncoding]];
}


- (NSString*)handleDictionaryEngine:(id)object{
    if([object isKindOfClass:[NSDictionary class]]){
        NSDictionary  * dict = object;
        NSInteger       count = dict.count;
        NSArray       * keyArr = [dict allKeys];
        for (NSInteger i = 0; i < count; i++) {
            id subObject = dict[keyArr[i]];
            if([subObject isKindOfClass:[NSDictionary class]]){
                [_jsonString appendFormat:@"\"%@\":{",keyArr[i]];
                [self handleDictionaryEngine:subObject];
                [_jsonString appendString:@"}"];
                if(i < count - 1){
                    [_jsonString appendString:@","];
                }
            }else if ([subObject isKindOfClass:[NSArray class]]){
                [_jsonString appendFormat:@"\"%@\":[",keyArr[i]];
                [self handleDictionaryEngine:subObject];
                [_jsonString appendString:@"]"];
                if(i < count - 1){
                    [_jsonString appendString:@","];
                }
            }else if([subObject isKindOfClass:[NSString class]]){
                [_jsonString appendFormat:@"\"%@\":\"%@\"",keyArr[i],subObject];
                if(i < count - 1){
                    [_jsonString appendString:@","];
                }
            }else if([subObject isKindOfClass:[NSNumber class]]){
                [_jsonString appendFormat:@"\"%@\":%@",keyArr[i],subObject];
                if(i < count - 1){
                    [_jsonString appendString:@","];
                }
            }
        }
    }else if([object isKindOfClass:[NSArray class]]){
        NSArray  * dictArr = object;
        NSInteger  count = dictArr.count;
        for (NSInteger i = 0; i < count; i++) {
            [_jsonString appendString:@"{"];
            [self handleDictionaryEngine:dictArr[i]];
            [_jsonString appendString:@"}"];
            if(i < count - 1){
                [_jsonString appendString:@","];
            }
        }
    }
    return _jsonString;
}

- (void)checkIsAddComma:(id)object{
    if(![object isKindOfClass:[NSArray class]] &&
       ![object isKindOfClass:[NSDictionary class]]){
        [_jsonString appendString:@","];
    }
}
@end


================================================
FILE: WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_XMLParser.h
================================================
//
//  WHC_XMLParse.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/4/28.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//
/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */
#import <Foundation/Foundation.h>

#define  kWHCCanFilterString (@":")                 //可过滤的字符串

typedef enum:NSInteger {
    WHC_XMLParserOptionsProcessNamespaces           = 1 << 0, // 指定是否接对象名称空间和元素的限定名称
    WHC_XMLParserOptionsReportNamespacePrefixes     = 1 << 1, // 指定是否接对象名称空间声明的范围
    WHC_XMLParserOptionsResolveExternalEntities     = 1 << 2, // 指定的接收对象声明是否外部实体
}WHC_XMLParserOptions;

/**
 * 说明 WHC_XMLParser xml解析器自动把xml字符串解析为字典对象(和json字符串解析为字典一样无任何多余key)
 */

@interface WHC_XMLParser : NSObject

/**
 * 说明: xml数据对象解析为字典
 * @param: data xml数据对象
 */

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data;

/**
 * 说明: xml数据对象解析为字典
 * @param: data xml数据对象
 */

+ (NSDictionary *)dictionaryForXMLString:(NSString *)string;

/**
 * 说明: xml数据对象解析为字典
 * @param: data xml数据对象
 * @param: options xml解析类型
 */

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data options:(WHC_XMLParserOptions)options;

/**
 * 说明: xml字符串对象解析为字典
 * @param: string xml字符串对象
 * @param: options xml解析类型
 */
+ (NSDictionary *)dictionaryForXMLString:(NSString *)string options:(WHC_XMLParserOptions)options;

/**
 * 说明: xml数据对象解析为字典
 * @param: data xml数据对象
 * @param: filterString xml解析过滤字符串
 */

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data filterString:(NSString *)filterString;

/**
 * 说明: xml字符串对象解析为字典
 * @param: string xml字符串对象
 * @param: filterString xml解析过滤字符串
 */

+ (NSDictionary *)dictionaryForXMLString:(NSString *)string filterString:(NSString *)filterString;

/**
 * 说明: xml数据对象解析为字典
 * @param: data xml数据对象
 * @param: filterString xml解析过滤字符串
 * @param: options xml解析类型
 */

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data filterString:(NSString *)filterString options:(WHC_XMLParserOptions)options;

/**
 * 说明: xml字符串对象解析为字典
 * @param: string xml字符串对象
 * @param: filterString xml解析过滤字符串
 * @param: options xml解析类型
 */

+ (NSDictionary *)dictionaryForXMLString:(NSString *)string filterString:(NSString *)filterString options:(WHC_XMLParserOptions)options;
@end


================================================
FILE: WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_XMLParser.m
================================================
//
//  WHC_XMLParse.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/4/28.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//
/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */
#import "WHC_XMLParser.h"

#define kWHCXMLParserTextNodeKey		(@"WHC_TXT")
@interface WHC_XMLParser ()<NSXMLParserDelegate>{
    NSMutableArray            *     _dictArr;             //存放字典数组
    NSMutableString           *     _contentTxt;          //存放当前解析内容文字
    NSError                   *     _error;               //存放错误信息
    NSString                  *     _filterString;        //要过滤字符串
}

@end

@implementation WHC_XMLParser

- (instancetype)init{
    self = [super init];
    if(self){
        _error = [NSError new];
        _dictArr = [NSMutableArray new];
        _contentTxt = [NSMutableString new];
    }
    return self;
}

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data{
    return [WHC_XMLParser dictionaryForXMLData:data options:0];
}

+ (NSDictionary *)dictionaryForXMLString:(NSString *)string{
    return [WHC_XMLParser dictionaryForXMLData:[string dataUsingEncoding:NSUTF8StringEncoding]];
}

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data options:(WHC_XMLParserOptions)options{
    WHC_XMLParser  * whc_xmlParser = [WHC_XMLParser new];
   return [whc_xmlParser startParserXML:data options:options];
}

+ (NSDictionary *)dictionaryForXMLString:(NSString *)string options:(WHC_XMLParserOptions)options{
    return [WHC_XMLParser dictionaryForXMLData:[string dataUsingEncoding:NSUTF8StringEncoding] options:options];
}

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data filterString:(NSString *)filterString{
    return [WHC_XMLParser dictionaryForXMLData:data filterString:filterString options:0];
}

+ (NSDictionary *)dictionaryForXMLString:(NSString *)string filterString:(NSString *)filterString{
    return [WHC_XMLParser dictionaryForXMLString:string filterString:filterString options:0];
}

+ (NSDictionary *)dictionaryForXMLData:(NSData *)data filterString:(NSString *)filterString options:(WHC_XMLParserOptions)options{
    WHC_XMLParser  * whc_xmlParser = [WHC_XMLParser new];
    [whc_xmlParser setFilterString:filterString];
    return [whc_xmlParser startParserXML:data options:options];
}

+ (NSDictionary *)dictionaryForXMLString:(NSString *)string filterString:(NSString *)filterString options:(WHC_XMLParserOptions)options{
    return [WHC_XMLParser dictionaryForXMLData:[string dataUsingEncoding:NSUTF8StringEncoding] filterString:filterString options:options];
}

- (void)setFilterString:(NSString*)filterString{
    if(filterString){
        _filterString = [filterString copy];
    }
}


- (NSDictionary*)startParserXML:(NSData*)data options:(WHC_XMLParserOptions)options{
    [_dictArr addObject:[NSMutableDictionary new]];
    NSXMLParser  * xmlParser = [[NSXMLParser alloc]initWithData:data];
    xmlParser.delegate = self;
    xmlParser.shouldProcessNamespaces = (options & WHC_XMLParserOptionsProcessNamespaces);
    xmlParser.shouldReportNamespacePrefixes = (options & WHC_XMLParserOptionsReportNamespacePrefixes);
    xmlParser.shouldResolveExternalEntities = (options & WHC_XMLParserOptionsResolveExternalEntities);
    if([xmlParser parse]){
        [self XMLDataHandleEngine:_dictArr[0]];
        return _dictArr[0];
    }
    return nil;
}

/// xml数据处理引擎 清除多余无用key
- (void)XMLDataHandleEngine:(id)object{
    if([object isKindOfClass:[NSDictionary class]]){
        NSMutableDictionary * dict = object;
        NSInteger               count = dict.count;
        NSArray              * keyArr = [dict allKeys];
        for (NSInteger i = 0; i < count; i++) {
            NSString  * key = keyArr[i];
            id   subObject = dict[key];
            if([subObject isKindOfClass:[NSDictionary class]]){
                [self handleTopData:dict subDict:subObject index:i];
                [self XMLDataHandleEngine:subObject];
            }else if([subObject isKindOfClass:[NSArray class]]){
                [self XMLDataHandleEngine:subObject];
            }
        }
    }else if ([object isKindOfClass:[NSArray class]]){
        NSMutableArray * arrs = object;
        for (NSInteger i = 0; i < arrs.count; i++) {
            id subObject = arrs[i];
            [self XMLDataHandleEngine:subObject];
        }
    }
}

- (void)handleTopData:(NSMutableDictionary *)dict subDict:(NSDictionary*)subDict index:(NSInteger)index{
    NSArray  * subKeyArr = [subDict allKeys];
    NSArray  * keyArr = [dict allKeys];
    if(subKeyArr.count == 1 && [subKeyArr[0] isEqualToString:kWHCXMLParserTextNodeKey]){
        [dict setObject:subDict[kWHCXMLParserTextNodeKey] forKey:keyArr[index]];
    }else if(subKeyArr.count == 0){
        [dict setObject:@"" forKey:keyArr[index]];
    }
}

- (NSString*)getAvailableElementName:(NSString*)elementName{
    NSString  *   handleElementName = [elementName copy];
    if(_filterString){
        if([handleElementName containsString:_filterString]){
            return [handleElementName stringByReplacingOccurrencesOfString:_filterString withString:@""];
        }
    }
    return handleElementName;
}

- (NSDictionary*)getAvailableAttributeDict:(NSDictionary *)attributeDict{
    NSMutableDictionary  * dict = [attributeDict mutableCopy];
    NSArray  * keyArr = [dict allKeys];
    for (NSString * key in keyArr) {
        if([key containsString:kWHCCanFilterString]){
            NSString * nKey = nil;
            nKey = [key stringByReplacingOccurrencesOfString:kWHCCanFilterString withString:@"_"];
            id value = dict[key];
            [dict setObject:value forKey:nKey];
            [dict removeObjectForKey:key];
        }
    }
    return dict;
}

#pragma mark - NSXMLParserDelegate
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
    NSString  *   handleElementName = [self getAvailableElementName:elementName];
    attributeDict = [self getAvailableAttributeDict:attributeDict];
    NSMutableDictionary  * parentDict = [_dictArr lastObject];
    NSMutableDictionary  * childDict = [NSMutableDictionary new];
    [childDict addEntriesFromDictionary:attributeDict];
    id existingValue = [parentDict objectForKey:handleElementName];
    if (existingValue){
        NSMutableArray *array = nil;
        if ([existingValue isKindOfClass:[NSMutableArray class]]){
            //使用存在的数组
            array = (NSMutableArray *) existingValue;
        }else{
            //不存在创建数组
            array = [NSMutableArray new];
            [array addObject:existingValue];
            // 替换子字典用数组
            [parentDict setObject:array forKey:handleElementName];
        }
        // 添加一个新的子字典
        [array addObject:childDict];
    }else{
        // 不存在插入新元素
        [parentDict setObject:childDict forKey:handleElementName];
    }
    
    // 跟新数组
    [_dictArr addObject:childDict];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    NSMutableDictionary *dictInProgress = [_dictArr lastObject];
    void (^saveValue)() = ^(){
        // 存储值
        NSString *valueTxt = [_contentTxt stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        if(valueTxt.length){
            [dictInProgress setObject:[valueTxt mutableCopy] forKey:kWHCXMLParserTextNodeKey];
        }
    };
    if (_contentTxt.length > 0){
        // 检测内容是否为json
        if(([_contentTxt hasPrefix:@"{"] && [_contentTxt hasSuffix:@"}"]) ||
           ([_contentTxt hasPrefix:@"["] && [_contentTxt hasSuffix:@"]"])){
            NSError  * err = nil;
            NSData * contentData = [_contentTxt dataUsingEncoding:NSUTF8StringEncoding];
            id contentObject = [NSJSONSerialization JSONObjectWithData:contentData options:NSJSONReadingMutableLeaves error:&err];
            if(err == nil){
                [dictInProgress setObject:contentObject forKey:kWHCXMLParserTextNodeKey];
            }else{
                saveValue();
            }
        }else{
            saveValue();
        }
        _contentTxt = [NSMutableString new];
    }
    // 移除当前
    [_dictArr removeLastObject];
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    [_contentTxt appendString:string];
    
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
    if(parseError){
        NSLog(@"WHC_XMLParserError :%@",parseError);
    }
}
@end


================================================
FILE: WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_Xml.h
================================================
//
//  WHC_Xml.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/4/29.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import <Foundation/Foundation.h>

/**
 * 说明: WHC_Xml dictionary对象转换为xml字符串
 * 默认 xml 编码类型为utf-8
 */

@interface WHC_Xml : NSObject

/**
 * 说明: dictionary对象转换为xml字符串
 * @param: dictionary 字典对象
 * @param: encode xml编码类型
 * @param: rootAttribute xml 根属性
 */

+ (NSString*)xmlWithDictionary:(NSDictionary*)dictionary
                        encode:(NSString*)encode
                 rootAttribute:(NSString*)rootAttribute;

/**
 * 说明: dictionary对象转换为xml字符串
 * @param: dictionary 字典对象
 * @param: encode xml编码类型
 */

+ (NSString*)xmlWithDictionary:(NSDictionary*)dictionary
                        encode:(NSString*)encode;

/**
 * 说明: dictionary对象转换为xml字符串
 * @param: dictionary 字典对象
 */

+ (NSString*)xmlWithDictionary:(NSDictionary*)dictionary;

/**
 * 说明: dictionary对象转换为xml字符串
 * @param: rootAttribute xml 根属性
 */

+ (NSString*)xmlWithDictionary:(NSDictionary*)dictionary
                 rootAttribute:(NSString*)rootAttribute;
@end


================================================
FILE: WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_Xml.m
================================================
//
//  WHC_Xml.m
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/4/29.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import "WHC_Xml.h"

@interface WHC_Xml (){
    NSMutableString              * _xmlString;
    NSString                     * _rootAttribute;
}

@end

@implementation WHC_Xml

- (instancetype)initWithEncode:(NSString *)encode attribute:(NSString*)attribute{
    self = [super init];
    if(self){
        _rootAttribute = attribute;
        _xmlString = [NSMutableString new];
        [_xmlString appendFormat:@"<?xml version=\"1.0\" encoding=\"%@\"?>",encode];
    }
    return self;
}

+ (NSString*)xmlWithDictionary:(NSDictionary*)dictionary encode:(NSString*)encode rootAttribute:(NSString*)rootAttribute{
    WHC_Xml  * whcXml = [[WHC_Xml alloc]initWithEncode:encode attribute:rootAttribute];
    return [whcXml handleDictionaryEngine:dictionary arrKey:@"" root:YES];
}

+ (NSString*)xmlWithDictionary:(NSDictionary*)dictionary encode:(NSString*)encode{
    return [WHC_Xml xmlWithDictionary:dictionary encode:encode rootAttribute:@""];
}

+ (NSString*)xmlWithDictionary:(NSDictionary*)dictionary{
    return [WHC_Xml xmlWithDictionary:dictionary encode:@"utf-8"];
}

+ (NSString*)xmlWithDictionary:(NSDictionary*)dictionary rootAttribute:(NSString*)rootAttribute{
    return [WHC_Xml xmlWithDictionary:dictionary encode:@"utf-8" rootAttribute:rootAttribute];
}

- (NSString*)handleDictionaryEngine:(id)object arrKey:(NSString*)arrKey root:(BOOL)root{
    if([object isKindOfClass:[NSDictionary class]]){
        NSDictionary  * dict = object;
        NSInteger       count = dict.count;
        NSArray       * keyArr = [dict allKeys];
        for (NSInteger i = 0; i < count; i++) {
            id subObject = dict[keyArr[i]];
            if([subObject isKindOfClass:[NSDictionary class]]){
                if(root && _rootAttribute && _rootAttribute.length){
                    [_xmlString appendFormat:@"<%@ %@>",keyArr[i],_rootAttribute];
                }else{
                    [_xmlString appendFormat:@"<%@>",keyArr[i]];
                }
                [self handleDictionaryEngine:subObject arrKey:@"" root:NO];
                [_xmlString appendFormat:@"</%@>",keyArr[i]];
            }else if ([subObject isKindOfClass:[NSArray class]]){
                [self handleDictionaryEngine:subObject arrKey:keyArr[i] root:NO];
            }else{
                [_xmlString appendFormat:@"<%@>%@</%@>",keyArr[i],subObject,keyArr[i]];
            }
        }
    }else if([object isKindOfClass:[NSArray class]]){
        NSArray  * dictArr = object;
        NSInteger  count = dictArr.count;
        for (NSInteger i = 0; i < count; i++) {
            [_xmlString appendFormat:@"<%@>",arrKey];
            [self handleDictionaryEngine:dictArr[i] arrKey:arrKey root:NO];
            [_xmlString appendFormat:@"</%@>",arrKey];
        }
    }
    if(_rootAttribute && _rootAttribute.length){
        
    }
    return _xmlString;
}
@end


================================================
FILE: WHCNetWorkKit/WHCNetWorkKit.h
================================================
//
//  WHCNetWorkKit.h
//  WHCNetWorkKit
//
//  Created by 吴海超 on 15/12/12.
//  Copyright © 2015年 吴海超. All rights reserved.
//

#import <UIKit/UIKit.h>

//! Project version number for WHCNetWorkKit.
FOUNDATION_EXPORT double WHCNetWorkKitVersionNumber;

//! Project version string for WHCNetWorkKit.
FOUNDATION_EXPORT const unsigned char WHCNetWorkKitVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <WHCNetWorkKit/PublicHeader.h>


#import <WHCNetWorkKit/WHC_HttpManager.h>
#import <WHCNetWorkKit/WHC_SessionDownloadManager.h>
#import <WHCNetWorkKit/UIButton+WHC_HttpButton.h>
#import <WHCNetWorkKit/UIImageView+WHC_HttpImageView.h>
#import <WHCNetWorkKit/WHC_DataModel.h>
#import <WHCNetWorkKit/WHC_Json.h>
#import <WHCNetWorkKit/WHC_Xml.h>
#import <WHCNetWorkKit/WHC_XMLParser.h>

================================================
FILE: WHCNetWorkKit Example/AppDelegate.h
================================================
//
//  AppDelegate.h
//  WHCNetWorkKit Example
//
//  Created by 吴海超 on 15/12/12.
//  Copyright © 2015年 吴海超. All rights reserved.
//

#import <UIKit/UIKit.h>

#define WHC_BackgroundDownload (0)

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;


@end



================================================
FILE: WHCNetWorkKit Example/AppDelegate.m
================================================
//
//  AppDelegate.m
//  WHCNetWorkKit Example
//
//  Created by 吴海超 on 15/12/12.
//  Copyright © 2015年 吴海超. All rights reserved.
//

#import "AppDelegate.h"
#import "ViewController.h"
#import <WHCNetWorkKit/WHC_HttpManager.h>
@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    _window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    _window.rootViewController = [[UINavigationController alloc]initWithRootViewController:[ViewController new]];
    [_window makeKeyAndVisible];
    return YES;
}

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
}

- (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: WHCNetWorkKit Example/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "3x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: WHCNetWorkKit Example/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8150" systemVersion="15A204g" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8122"/>
    </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"/>
                        <animations/>
                        <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: WHCNetWorkKit Example/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>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
	</dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>com.WHC.WHCNetWorkKit</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>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
FILE: WHCNetWorkKit Example/UI/WHC_FillScreenPlayerVC.h
================================================
//
//  WHC_FillScreenPlayerVC.h
//  PhoneBookBag
//
//  Created by 吴海超 on 15/7/8.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  iOSqq群:302157745
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import <UIKit/UIKit.h>
@interface WHC_FillScreenPlayerVC : UIViewController

@property (nonatomic , strong)NSURL  * playUrl;
@end


================================================
FILE: WHCNetWorkKit Example/UI/WHC_FillScreenPlayerVC.m
================================================
//
//  WHC_FillScreenPlayerVC.m
//  PhoneBookBag
//
//  Created by 吴海超 on 15/7/8.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//

/*
 *  qq:712641411
 *  iOSqq群:302157745
 *  gitHub:https://github.com/netyouli
 *  csdn:http://blog.csdn.net/windwhc/article/category/3117381
 */

#import "WHC_FillScreenPlayerVC.h"
#import <MediaPlayer/MediaPlayer.h>
#import "UIView+WHC_ViewProperty.h"
#import "UIView+WHC_Loading.h"
#define kRotateAnimationDuring         (0.2)       //旋转动画
@interface WHC_FillScreenPlayerVC (){
    MPMoviePlayerController  *               _moviePlayer;      //视频播放器
    CGRect                                   _moviePlayerRect;  //初始视频区域
    BOOL                                     _visableStatusBar;      //状态栏是否可见
    BOOL                                     _isRotate;         //是否旋转
}

@end

@implementation WHC_FillScreenPlayerVC

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initData];
    [self layoutUI];
    // Do any additional setup after loading the view.
}

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self.view startLoading];
}

- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
}

- (void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:animated];
    [self removeMovieNotificationHandlers];
    [self showNavigationBar];
}

- (void)layoutUI{
    [self hideNavigationBar];
    self.view.backgroundColor = [UIColor whiteColor];
    _moviePlayer = [[MPMoviePlayerController alloc]init];
    _moviePlayer.controlStyle = MPMovieControlStyleDefault;
    _moviePlayer.movieSourceType = MPMovieScalingModeAspectFit;
    _moviePlayer.shouldAutoplay = YES;
    _moviePlayer.view.frame = _moviePlayerRect;
    [self.view addSubview:_moviePlayer.view];
    _moviePlayer.contentURL = _playUrl;
    [_moviePlayer prepareToPlay];
    [_moviePlayer play];
}

- (void)initData{
    _moviePlayerRect = [UIScreen mainScreen].bounds;
    [self installMovieNotificationObservers];
}

- (void)moviePlayerReadyForDisplay:(NSNotification *)notifiy{
    [self.view stopLoading];
}

- (void)showNavigationBar{
    _visableStatusBar = NO;
    self.navigationController.navigationBarHidden = NO;
    if([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]){
        [self prefersStatusBarHidden];
        [self setNeedsStatusBarAppearanceUpdate];
    }
}

- (void)hideNavigationBar{
    _visableStatusBar = YES;
    self.navigationController.navigationBarHidden = YES;
    if([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]){
        [self prefersStatusBarHidden];
        [self setNeedsStatusBarAppearanceUpdate];
    }
}

- (BOOL)prefersStatusBarHidden{
    return _visableStatusBar;
}

- (void)scanButton:(UIView *)view visable:(BOOL)visable{
    NSArray  * subViewArr = view.subviews;
    if(subViewArr && subViewArr.count > 0){
        for (UIButton * btn in subViewArr) {
            if([btn isKindOfClass:[UIButton class]]){
                if([btn.titleLabel.text isEqualToString:@"Done"] ||
                   [btn.titleLabel.text isEqualToString:@"完成"]){
                    [btn addTarget:self action:@selector(clickDone:) forControlEvents:UIControlEventTouchUpInside];
                }else if(btn.x < 160 + 5 && btn.x > 160 - 5){
                    btn.hidden = NO;
                }else{
                    btn.hidden = !visable;
                }
            }else{
                [self scanButton:btn visable:visable];
            }
        }
    }
}

- (void)clickDone:(UIButton *)sender{
    _moviePlayer.view.xy = _moviePlayerRect.origin;
 
Download .txt
gitextract_dw57sunh/

├── LICENSE
├── README.md
├── WHCNetWorkKit/
│   ├── Info.plist
│   ├── NSURLConnection/
│   │   ├── WHC_BaseOperation.h
│   │   ├── WHC_BaseOperation.m
│   │   ├── WHC_DownloadOperation.h
│   │   ├── WHC_DownloadOperation.m
│   │   ├── WHC_HttpManager.h
│   │   ├── WHC_HttpManager.m
│   │   ├── WHC_HttpOperation.h
│   │   └── WHC_HttpOperation.m
│   ├── NSURLSession/
│   │   ├── WHC_DownloadSessionTask.h
│   │   ├── WHC_DownloadSessionTask.m
│   │   ├── WHC_SessionDownloadManager.h
│   │   └── WHC_SessionDownloadManager.m
│   ├── Reachability/
│   │   ├── Reachability.h
│   │   └── Reachability.m
│   ├── UIKit+WHCNetWorkKit/
│   │   ├── UIButton+WHC_HttpButton.h
│   │   ├── UIButton+WHC_HttpButton.m
│   │   ├── UIImageView+WHC_HttpImageView.h
│   │   ├── UIImageView+WHC_HttpImageView.m
│   │   ├── WHC_ImageCache.h
│   │   └── WHC_ImageCache.m
│   ├── UtilKit+WHCNetWorkKit/
│   │   ├── WHC_DataModel.h
│   │   ├── WHC_DataModel.m
│   │   ├── WHC_Json.h
│   │   ├── WHC_Json.m
│   │   ├── WHC_XMLParser.h
│   │   ├── WHC_XMLParser.m
│   │   ├── WHC_Xml.h
│   │   └── WHC_Xml.m
│   └── WHCNetWorkKit.h
├── WHCNetWorkKit Example/
│   ├── AppDelegate.h
│   ├── AppDelegate.m
│   ├── Assets.xcassets/
│   │   └── AppIcon.appiconset/
│   │       └── Contents.json
│   ├── Base.lproj/
│   │   └── LaunchScreen.storyboard
│   ├── Info.plist
│   ├── UI/
│   │   ├── WHC_FillScreenPlayerVC.h
│   │   ├── WHC_FillScreenPlayerVC.m
│   │   ├── WHC_OffLineVideoCell.xib
│   │   ├── WHC_OffLineVideoVC.h
│   │   ├── WHC_OffLineVideoVC.m
│   │   └── WHC_OffLineVideoVC.xib
│   ├── UIUnitCore/
│   │   ├── UIScrollView+WHC_PullRefresh.h
│   │   ├── UIScrollView+WHC_PullRefresh.m
│   │   ├── UIView+WHC_Loading.h
│   │   ├── UIView+WHC_Loading.m
│   │   ├── UIView+WHC_Toast.h
│   │   ├── UIView+WHC_Toast.m
│   │   ├── UIView+WHC_ViewProperty.h
│   │   └── UIView+WHC_ViewProperty.m
│   ├── ViewController.h
│   ├── ViewController.m
│   ├── ViewController.xib
│   ├── WHC_DownloadObject.h
│   ├── WHC_DownloadObject.m
│   └── main.m
├── WHCNetWorkKit Example.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcuserdata/
│   │       └── wuhaichao.xcuserdatad/
│   │           └── UserInterfaceState.xcuserstate
│   └── xcuserdata/
│       ├── WHC.xcuserdatad/
│       │   └── xcschemes/
│       │       ├── WHCNetWorkKit Example.xcscheme
│       │       └── xcschememanagement.plist
│       └── wuhaichao.xcuserdatad/
│           └── xcschemes/
│               ├── WHCNetWorkKit Example.xcscheme
│               └── xcschememanagement.plist
├── WHCNetWorkKit ExampleTests/
│   ├── Info.plist
│   └── WHCNetWorkKit_ExampleTests.m
├── WHCNetWorkKit ExampleUITests/
│   ├── Info.plist
│   └── WHCNetWorkKit_ExampleUITests.m
├── WHCNetWorkKit.podspec
├── WHCNetWorkKit.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   ├── contents.xcworkspacedata
│   │   └── xcuserdata/
│   │       └── wuhaichao.xcuserdatad/
│   │           └── UserInterfaceState.xcuserstate
│   └── xcuserdata/
│       ├── WHC.xcuserdatad/
│       │   └── xcschemes/
│       │       ├── WHCNetWorkKit.xcscheme
│       │       └── xcschememanagement.plist
│       └── wuhaichao.xcuserdatad/
│           └── xcschemes/
│               ├── WHCNetWorkKit.xcscheme
│               └── xcschememanagement.plist
├── WHCNetWorkKit.xcworkspace/
│   ├── contents.xcworkspacedata
│   └── xcuserdata/
│       ├── WHC.xcuserdatad/
│       │   ├── UserInterfaceState.xcuserstate
│       │   └── xcdebugger/
│       │       └── Breakpoints_v2.xcbkptlist
│       └── wuhaichao.xcuserdatad/
│           ├── UserInterfaceState.xcuserstate
│           ├── xcdebugger/
│           │   └── Breakpoints_v2.xcbkptlist
│           └── xcschemes/
│               └── xcschememanagement.plist
└── WHCNetWorkKitTests/
    ├── Info.plist
    └── WHCNetWorkKitTests.m
Download .txt
SYMBOL INDEX (6 symbols across 4 files)

FILE: WHCNetWorkKit Example/UIUnitCore/UIScrollView+WHC_PullRefresh.h
  type WHCPullRefreshStyle (line 18) | typedef enum {

FILE: WHCNetWorkKit Example/UIUnitCore/UIView+WHC_Toast.h
  type WHC_TOAST_POSTION (line 11) | typedef enum{
  type WHC_TOAST_TYPE (line 17) | typedef enum {

FILE: WHCNetWorkKit/Reachability/Reachability.h
  type NetworkStatus (line 53) | typedef enum : NSInteger {
  type sockaddr_in (line 73) | struct sockaddr_in

FILE: WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_XMLParser.h
  type WHC_XMLParserOptions (line 17) | typedef enum:NSInteger {
Condensed preview — 84 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (419K chars).
[
  {
    "path": "LICENSE",
    "chars": 1070,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 吴海超\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
  },
  {
    "path": "README.md",
    "chars": 14422,
    "preview": "# WHCNetWorkKit 网络操作开源库\n\n###咨询QQ:712641411     \n###开发作者:吴海超\n\n###目前封装最好使用最简单的文件下载(支持后台下载)iOS网络开源库 该版本进行了增强包括如下功能:\n###GET/"
  },
  {
    "path": "WHCNetWorkKit/Info.plist",
    "chars": 806,
    "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": "WHCNetWorkKit/NSURLConnection/WHC_BaseOperation.h",
    "chars": 6192,
    "preview": "//\n//  WHC_BaseOperation.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All rights res"
  },
  {
    "path": "WHCNetWorkKit/NSURLConnection/WHC_BaseOperation.m",
    "chars": 10107,
    "preview": "//\n//  WHC_BaseOperation.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All rights res"
  },
  {
    "path": "WHCNetWorkKit/NSURLConnection/WHC_DownloadOperation.h",
    "chars": 1315,
    "preview": "//\n//  WHC_DownloadOperation.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All rights"
  },
  {
    "path": "WHCNetWorkKit/NSURLConnection/WHC_DownloadOperation.m",
    "chars": 8033,
    "preview": "//\n//  WHC_DownloadOperation.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All rights"
  },
  {
    "path": "WHCNetWorkKit/NSURLConnection/WHC_HttpManager.h",
    "chars": 9488,
    "preview": "//\n//  WHC_HttpManager.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All rights reser"
  },
  {
    "path": "WHCNetWorkKit/NSURLConnection/WHC_HttpManager.m",
    "chars": 29343,
    "preview": "//\n//  WHC_HttpManager.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All rights reser"
  },
  {
    "path": "WHCNetWorkKit/NSURLConnection/WHC_HttpOperation.h",
    "chars": 345,
    "preview": "//\n//  WHC_HttpOperation.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All rights res"
  },
  {
    "path": "WHCNetWorkKit/NSURLConnection/WHC_HttpOperation.m",
    "chars": 2772,
    "preview": "//\n//  WHC_HttpOperation.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All rights res"
  },
  {
    "path": "WHCNetWorkKit/NSURLSession/WHC_DownloadSessionTask.h",
    "chars": 736,
    "preview": "//\n//  WHC_DownloadSessionTask.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/12/7.\n//  Copyright © 2015年 吴海超. All righ"
  },
  {
    "path": "WHCNetWorkKit/NSURLSession/WHC_DownloadSessionTask.m",
    "chars": 573,
    "preview": "//\n//  WHC_DownloadSessionTask.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/12/7.\n//  Copyright © 2015年 吴海超. All righ"
  },
  {
    "path": "WHCNetWorkKit/NSURLSession/WHC_SessionDownloadManager.h",
    "chars": 5178,
    "preview": "//\n//  WHC_SessionDownloadOperation.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/30.\n//  Copyright © 2015年 吴海超. Al"
  },
  {
    "path": "WHCNetWorkKit/NSURLSession/WHC_SessionDownloadManager.m",
    "chars": 22495,
    "preview": "//\n//  WHC_SessionDownloadOperation.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/30.\n//  Copyright © 2015年 吴海超. Al"
  },
  {
    "path": "WHCNetWorkKit/Reachability/Reachability.h",
    "chars": 3722,
    "preview": "/*\n     File: Reachability.h\n Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.\n  Ve"
  },
  {
    "path": "WHCNetWorkKit/Reachability/Reachability.m",
    "chars": 9617,
    "preview": "/*\n     File: Reachability.m\n Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.\n  Ve"
  },
  {
    "path": "WHCNetWorkKit/UIKit+WHCNetWorkKit/UIButton+WHC_HttpButton.h",
    "chars": 1286,
    "preview": "//\n//  UIButton+WHC_HttpButton.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All righ"
  },
  {
    "path": "WHCNetWorkKit/UIKit+WHCNetWorkKit/UIButton+WHC_HttpButton.m",
    "chars": 8138,
    "preview": "//\n//  UIButton+WHC_HttpButton.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All righ"
  },
  {
    "path": "WHCNetWorkKit/UIKit+WHCNetWorkKit/UIImageView+WHC_HttpImageView.h",
    "chars": 763,
    "preview": "//\n//  UIImageView+WHC_HttpImageView.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. Al"
  },
  {
    "path": "WHCNetWorkKit/UIKit+WHCNetWorkKit/UIImageView+WHC_HttpImageView.m",
    "chars": 6870,
    "preview": "//\n//  UIImageView+WHC_HttpImageView.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. Al"
  },
  {
    "path": "WHCNetWorkKit/UIKit+WHCNetWorkKit/WHC_ImageCache.h",
    "chars": 1501,
    "preview": "//\n//  WHC_ImageCache.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All rights reserv"
  },
  {
    "path": "WHCNetWorkKit/UIKit+WHCNetWorkKit/WHC_ImageCache.m",
    "chars": 6322,
    "preview": "//\n//  WHC_ImageCache.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/11/6.\n//  Copyright © 2015年 吴海超. All rights reserv"
  },
  {
    "path": "WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_DataModel.h",
    "chars": 1093,
    "preview": "//\n//  WHC_DataModel.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/4/29.\n//  Copyright (c) 2015年 吴海超. All rights reser"
  },
  {
    "path": "WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_DataModel.m",
    "chars": 10933,
    "preview": "//\n//  WHC_DataModel.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/4/29.\n//  Copyright (c) 2015年 吴海超. All rights reser"
  },
  {
    "path": "WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_Json.h",
    "chars": 847,
    "preview": "//\n//  WHC_Json.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/4/29.\n//  Copyright (c) 2015年 吴海超. All rights reserved.\n"
  },
  {
    "path": "WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_Json.m",
    "chars": 3771,
    "preview": "//\n//  WHC_Json.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/4/29.\n//  Copyright (c) 2015年 吴海超. All rights reserved.\n"
  },
  {
    "path": "WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_XMLParser.h",
    "chars": 2225,
    "preview": "//\n//  WHC_XMLParse.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/4/28.\n//  Copyright (c) 2015年 吴海超. All rights reserv"
  },
  {
    "path": "WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_XMLParser.m",
    "chars": 8601,
    "preview": "//\n//  WHC_XMLParse.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/4/28.\n//  Copyright (c) 2015年 吴海超. All rights reserv"
  },
  {
    "path": "WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_Xml.h",
    "chars": 1184,
    "preview": "//\n//  WHC_Xml.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/4/29.\n//  Copyright (c) 2015年 吴海超. All rights reserved.\n/"
  },
  {
    "path": "WHCNetWorkKit/UtilKit+WHCNetWorkKit/WHC_Xml.m",
    "chars": 3099,
    "preview": "//\n//  WHC_Xml.m\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/4/29.\n//  Copyright (c) 2015年 吴海超. All rights reserved.\n/"
  },
  {
    "path": "WHCNetWorkKit/WHCNetWorkKit.h",
    "chars": 858,
    "preview": "//\n//  WHCNetWorkKit.h\n//  WHCNetWorkKit\n//\n//  Created by 吴海超 on 15/12/12.\n//  Copyright © 2015年 吴海超. All rights reserv"
  },
  {
    "path": "WHCNetWorkKit Example/AppDelegate.h",
    "chars": 313,
    "preview": "//\n//  AppDelegate.h\n//  WHCNetWorkKit Example\n//\n//  Created by 吴海超 on 15/12/12.\n//  Copyright © 2015年 吴海超. All rights "
  },
  {
    "path": "WHCNetWorkKit Example/AppDelegate.m",
    "chars": 2483,
    "preview": "//\n//  AppDelegate.m\n//  WHCNetWorkKit Example\n//\n//  Created by 吴海超 on 15/12/12.\n//  Copyright © 2015年 吴海超. All rights "
  },
  {
    "path": "WHCNetWorkKit Example/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 585,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "WHCNetWorkKit Example/Base.lproj/LaunchScreen.storyboard",
    "chars": 1664,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "WHCNetWorkKit Example/Info.plist",
    "chars": 1240,
    "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": "WHCNetWorkKit Example/UI/WHC_FillScreenPlayerVC.h",
    "chars": 415,
    "preview": "//\n//  WHC_FillScreenPlayerVC.h\n//  PhoneBookBag\n//\n//  Created by 吴海超 on 15/7/8.\n//  Copyright (c) 2015年 吴海超. All right"
  },
  {
    "path": "WHCNetWorkKit Example/UI/WHC_FillScreenPlayerVC.m",
    "chars": 9663,
    "preview": "//\n//  WHC_FillScreenPlayerVC.m\n//  PhoneBookBag\n//\n//  Created by 吴海超 on 15/7/8.\n//  Copyright (c) 2015年 吴海超. All right"
  },
  {
    "path": "WHCNetWorkKit Example/UI/WHC_OffLineVideoCell.xib",
    "chars": 5521,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "WHCNetWorkKit Example/UI/WHC_OffLineVideoVC.h",
    "chars": 844,
    "preview": "//\n//  WHC_OffLineVideoVC.h\n//  DingLibrary\n//\n//  Created by 吴海超 on 15/7/9.\n//  Copyright (c) 2015年 Rudy. All rights re"
  },
  {
    "path": "WHCNetWorkKit Example/UI/WHC_OffLineVideoVC.m",
    "chars": 19164,
    "preview": "//\n//  WHC_OffLineVideoVC.m\n//  DingLibrary\n//\n//  Created by 吴海超 on 15/7/9.\n//  Copyright (c) 2015年 Rudy. All rights re"
  },
  {
    "path": "WHCNetWorkKit Example/UI/WHC_OffLineVideoVC.xib",
    "chars": 2579,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "WHCNetWorkKit Example/UIUnitCore/UIScrollView+WHC_PullRefresh.h",
    "chars": 822,
    "preview": "//\n//  UIScrollView+WHC_PullRefresh.h\n//  PhoneBookBag\n//\n//  Created by 吴海超 on 14/8/20.\n//  Copyright (c) 2014年 吴海超. Al"
  },
  {
    "path": "WHCNetWorkKit Example/UIUnitCore/UIScrollView+WHC_PullRefresh.m",
    "chars": 34092,
    "preview": "//\n//  UIScrollView+WHC_PullRefresh.m\n//  PhoneBookBag\n//\n//  Created by 吴海超 on 14/8/20.\n//  Copyright (c) 2014年 吴海超. Al"
  },
  {
    "path": "WHCNetWorkKit Example/UIUnitCore/UIView+WHC_Loading.h",
    "chars": 472,
    "preview": "//\n//  UIView+WHC_Loading.h\n//  UIView+WHC_Loading\n//\n//  Created by 吴海超 on 15/3/25.\n//  Copyright (c) 2015年 吴海超. All ri"
  },
  {
    "path": "WHCNetWorkKit Example/UIUnitCore/UIView+WHC_Loading.m",
    "chars": 3905,
    "preview": "//\n//  UIView+WHC_Loading.m\n//  UIView+WHC_Loading\n//\n//  Created by 吴海超 on 15/3/25.\n//  Copyright (c) 2015年 吴海超. All ri"
  },
  {
    "path": "WHCNetWorkKit Example/UIUnitCore/UIView+WHC_Toast.h",
    "chars": 852,
    "preview": "//\n//  UIView+WHC_Toast.h\n//  UIView+WHC_Toast\n//\n//  Created by 吴海超 on 15/3/24.\n//  Copyright (c) 2015年 吴海超. All rights"
  },
  {
    "path": "WHCNetWorkKit Example/UIUnitCore/UIView+WHC_Toast.m",
    "chars": 4639,
    "preview": "//\n//  UIView+WHC_Toast.m\n//  UIView+WHC_Toast\n//\n//  Created by 吴海超 on 15/3/24.\n//  Copyright (c) 2015年 吴海超. All rights"
  },
  {
    "path": "WHCNetWorkKit Example/UIUnitCore/UIView+WHC_ViewProperty.h",
    "chars": 843,
    "preview": "//\n//  UIView+WHC_ViewProperty.h\n//  WHC_ ContainerView\n//\n//  Created by 吴海超 on 15/5/15.\n//  Copyright (c) 2015年 吴海超. A"
  },
  {
    "path": "WHCNetWorkKit Example/UIUnitCore/UIView+WHC_ViewProperty.m",
    "chars": 1981,
    "preview": "//\n//  UIView+WHC_ViewProperty.m\n//  WHC_ ContainerView\n//\n//  Created by 吴海超 on 15/5/15.\n//  Copyright (c) 2015年 吴海超. A"
  },
  {
    "path": "WHCNetWorkKit Example/ViewController.h",
    "chars": 363,
    "preview": "//\n//  ViewController.h\n//  WHC_FileDownloadDemo\n//\n//  Created by 吴海超 on 15/7/27.\n//  Copyright (c) 2015年 吴海超. All righ"
  },
  {
    "path": "WHCNetWorkKit Example/ViewController.m",
    "chars": 10895,
    "preview": "//\n//  ViewController.m\n//  WHC_FileDownloadDemo\n//\n//  Created by 吴海超 on 15/7/27.\n//  Copyright (c) 2015年 吴海超. All righ"
  },
  {
    "path": "WHCNetWorkKit Example/ViewController.xib",
    "chars": 2495,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
  },
  {
    "path": "WHCNetWorkKit Example/WHC_DownloadObject.h",
    "chars": 1439,
    "preview": "//\n//  WHC_DownloadObject.h\n//  WHC_FileDownloadDemo\n//\n//  Created by 吴海超 on 15/11/27.\n//  Copyright © 2015年 吴海超. All r"
  },
  {
    "path": "WHCNetWorkKit Example/WHC_DownloadObject.m",
    "chars": 6198,
    "preview": "//\n//  WHC_DownloadObject.m\n//  WHC_FileDownloadDemo\n//\n//  Created by 吴海超 on 15/11/27.\n//  Copyright © 2015年 吴海超. All r"
  },
  {
    "path": "WHCNetWorkKit Example/main.m",
    "chars": 334,
    "preview": "//\n//  main.m\n//  WHCNetWorkKit Example\n//\n//  Created by 吴海超 on 15/12/12.\n//  Copyright © 2015年 吴海超. All rights reserve"
  },
  {
    "path": "WHCNetWorkKit Example.xcodeproj/project.pbxproj",
    "chars": 27952,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "WHCNetWorkKit Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 166,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:WHCNetWorkKit E"
  },
  {
    "path": "WHCNetWorkKit Example.xcodeproj/xcuserdata/WHC.xcuserdatad/xcschemes/WHCNetWorkKit Example.xcscheme",
    "chars": 4419,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0730\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "WHCNetWorkKit Example.xcodeproj/xcuserdata/WHC.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 673,
    "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": "WHCNetWorkKit Example.xcodeproj/xcuserdata/wuhaichao.xcuserdatad/xcschemes/WHCNetWorkKit Example.xcscheme",
    "chars": 4417,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0710\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "WHCNetWorkKit Example.xcodeproj/xcuserdata/wuhaichao.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 673,
    "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": "WHCNetWorkKit ExampleTests/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": "WHCNetWorkKit ExampleTests/WHCNetWorkKit_ExampleTests.m",
    "chars": 941,
    "preview": "//\n//  WHCNetWorkKit_ExampleTests.m\n//  WHCNetWorkKit ExampleTests\n//\n//  Created by 吴海超 on 15/12/12.\n//  Copyright © 20"
  },
  {
    "path": "WHCNetWorkKit ExampleUITests/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": "WHCNetWorkKit ExampleUITests/WHCNetWorkKit_ExampleUITests.m",
    "chars": 1248,
    "preview": "//\n//  WHCNetWorkKit_ExampleUITests.m\n//  WHCNetWorkKit ExampleUITests\n//\n//  Created by 吴海超 on 15/12/12.\n//  Copyright "
  },
  {
    "path": "WHCNetWorkKit.podspec",
    "chars": 1851,
    "preview": "Pod::Spec.new do |s|\n  s.name         = 'WHCNetWorkKit'\n  s.version      = '0.0.3'\n  s.summary      = 'WHCNetWorkKit 是ht"
  },
  {
    "path": "WHCNetWorkKit.xcodeproj/project.pbxproj",
    "chars": 28596,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "WHCNetWorkKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 158,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:WHCNetWorkKit.x"
  },
  {
    "path": "WHCNetWorkKit.xcodeproj/xcuserdata/WHC.xcuserdatad/xcschemes/WHCNetWorkKit.xcscheme",
    "chars": 3733,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0730\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "WHCNetWorkKit.xcodeproj/xcuserdata/WHC.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 575,
    "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": "WHCNetWorkKit.xcodeproj/xcuserdata/wuhaichao.xcuserdatad/xcschemes/WHCNetWorkKit.xcscheme",
    "chars": 3733,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0710\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "WHCNetWorkKit.xcodeproj/xcuserdata/wuhaichao.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 575,
    "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": "WHCNetWorkKit.xcworkspace/contents.xcworkspacedata",
    "chars": 243,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:WHCNetWorkKit."
  },
  {
    "path": "WHCNetWorkKit.xcworkspace/xcuserdata/WHC.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
    "chars": 2933,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n   type = \"0\"\n   version = \"2.0\">\n   <Breakpoints>\n      <BreakpointProxy"
  },
  {
    "path": "WHCNetWorkKit.xcworkspace/xcuserdata/wuhaichao.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist",
    "chars": 91,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Bucket\n   type = \"0\"\n   version = \"2.0\">\n</Bucket>\n"
  },
  {
    "path": "WHCNetWorkKit.xcworkspace/xcuserdata/wuhaichao.xcuserdatad/xcschemes/xcschememanagement.plist",
    "chars": 225,
    "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": "WHCNetWorkKitTests/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": "WHCNetWorkKitTests/WHCNetWorkKitTests.m",
    "chars": 909,
    "preview": "//\n//  WHCNetWorkKitTests.m\n//  WHCNetWorkKitTests\n//\n//  Created by 吴海超 on 15/12/12.\n//  Copyright © 2015年 吴海超. All rig"
  }
]

// ... and 4 more files (download for full content)

About this extraction

This page contains the full source code of the netyouli/WHC_FileDownloadDemo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 84 files (374.8 KB), approximately 102.6k tokens, and a symbol index with 6 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!