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"
```
##运行效果

###网络状态监听 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;
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
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.