├── TYHttpManagerDemo ├── MBProgressHUD │ ├── MBProgressHUD.bundle │ │ ├── error.png │ │ ├── info.png │ │ ├── error@2x.png │ │ ├── info@2x.png │ │ ├── info@3x.png │ │ ├── success.png │ │ └── success@2x.png │ ├── MBProgressHUD+MJ.h │ ├── MBProgressHUD+MJ.m │ └── MBProgressHUD.h ├── ViewController.h ├── TYJSONModel │ ├── TYJSONModel.h │ ├── TYClassInfo.h │ ├── TYPropertyInfo.h │ ├── NSObject+TYJSONModel.h │ ├── TYClassInfo.m │ ├── TYPropertyInfo.m │ └── NSObject+TYJSONModel.m ├── AppDelegate.h ├── main.m ├── TCategoryRequest.h ├── TCatergoryModel.m ├── TYHttpManager │ ├── TYRequstConfigure.h │ ├── TYRequstConfigure.m │ ├── TYResponseCache.h │ ├── TYHttpManager.h │ ├── TYResponseObject.h │ ├── TYChainRequest.h │ ├── TYBatchRequest.h │ ├── TYHttpRequest.h │ ├── TYResponseObject.m │ ├── TYRequestProtocol.h │ ├── TYBaseRequest.h │ ├── TYBatchRequest.m │ ├── TYChainRequest.m │ ├── TYBaseRequest.m │ ├── TYHttpRequest.m │ ├── TYResponseCache.m │ └── TYHttpManager.m ├── THttpRequest.h ├── TResponseObject.h ├── THttpRequest.m ├── TCatergoryModel.h ├── TCategoryRequest.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── AFNetworking │ ├── AFNetworking.h │ ├── AFSecurityPolicy.h │ ├── AFNetworkReachabilityManager.h │ ├── AFNetworkReachabilityManager.m │ ├── AFURLResponseSerialization.h │ ├── AFSecurityPolicy.m │ ├── AFHTTPSessionManager.m │ └── AFHTTPSessionManager.h ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── TResponseObject.m ├── AppDelegate.m └── ViewController.m ├── TYHttpManagerDemo.xcodeproj ├── xcuserdata │ └── tany.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── TYHttpManagerDemo.xcscheme └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── tany.xcuserdatad │ └── UserInterfaceState.xcuserstate └── README.md /TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12207480/TYHttpManager/HEAD/TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/error.png -------------------------------------------------------------------------------- /TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12207480/TYHttpManager/HEAD/TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/info.png -------------------------------------------------------------------------------- /TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12207480/TYHttpManager/HEAD/TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/error@2x.png -------------------------------------------------------------------------------- /TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/info@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12207480/TYHttpManager/HEAD/TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/info@2x.png -------------------------------------------------------------------------------- /TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/info@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12207480/TYHttpManager/HEAD/TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/info@3x.png -------------------------------------------------------------------------------- /TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12207480/TYHttpManager/HEAD/TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/success.png -------------------------------------------------------------------------------- /TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/success@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12207480/TYHttpManager/HEAD/TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.bundle/success@2x.png -------------------------------------------------------------------------------- /TYHttpManagerDemo.xcodeproj/xcuserdata/tany.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TYHttpManager 2 | 网络请求管理库,基于对AFNetwork的封装
3 | 支持httpRequest,(链式)chainRequest,(批量)batchRequest
4 | 支持数据缓存,josnModel转换
5 | 用法请看 demo
6 | 详细的使用请看[LovePlayNews](https://github.com/12207480/LovePlayNews)项目 7 | -------------------------------------------------------------------------------- /TYHttpManagerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TYHttpManagerDemo.xcodeproj/project.xcworkspace/xcuserdata/tany.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/12207480/TYHttpManager/HEAD/TYHttpManagerDemo.xcodeproj/project.xcworkspace/xcuserdata/tany.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /TYHttpManagerDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/20. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYJSONModel/TYJSONModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYJSONModel.h 3 | // TYJSONModelDemo 4 | // 5 | // Created by tany on 16/4/8. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #ifndef TYJSONModel_h 10 | #define TYJSONModel_h 11 | 12 | #import "NSObject+TYJSONModel.h" 13 | #import "TYClassInfo.h" 14 | 15 | #endif /* TYJSONModel_h */ 16 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/20. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/20. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TCategoryRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // TCategoryRequest.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/24. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "THttpRequest.h" 10 | #import "TCatergoryModel.h" 11 | 12 | @interface TCategoryRequest : THttpRequest 13 | 14 | + (instancetype)requestWithGender:(NSString *)gender generation:(NSString *)generation; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TCatergoryModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TCatergoryModel.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/24. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TCatergoryModel.h" 10 | #import "TYJSONModel.h" 11 | 12 | @implementation TCatergoryData 13 | 14 | + (NSDictionary *)modelClassInArrayOrDictonary 15 | { 16 | return @{@"secondary_banners":[TCatergoryModel class]}; 17 | } 18 | 19 | 20 | @end 21 | 22 | @implementation TCatergoryModel 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYRequstConfigure.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYRequstConfigure.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/23. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TYRequstConfigure : NSObject 12 | 13 | @property (nonatomic, strong) NSString *baseURL; 14 | 15 | // session configure 16 | @property (nonatomic, strong) NSURLSessionConfiguration *sessionConfiguration; 17 | 18 | + (TYRequstConfigure *)sharedInstance; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYJSONModel/TYClassInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYClassInfo.h 3 | // TYJSONModelDemo 4 | // 5 | // Created by tany on 16/4/6. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TYPropertyInfo.h" 11 | 12 | @interface TYClassInfo : NSObject 13 | 14 | @property(nonatomic,strong, readonly) NSDictionary *propertyInfo;// 属性字典 15 | @property(nonatomic,assign, readonly) Class cls; // class 16 | 17 | - (instancetype)initWithClass:(Class )cls; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYRequstConfigure.m: -------------------------------------------------------------------------------- 1 | // 2 | // TYRequstConfigure.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/23. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYRequstConfigure.h" 10 | 11 | @implementation TYRequstConfigure 12 | 13 | + (TYRequstConfigure *)sharedInstance { 14 | static id sharedInstance = nil; 15 | static dispatch_once_t onceToken; 16 | dispatch_once(&onceToken, ^{ 17 | sharedInstance = [[self alloc] init]; 18 | }); 19 | return sharedInstance; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/THttpRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // THttpRequest.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/24. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYHttpRequest.h" 10 | #import "TResponseObject.h" 11 | 12 | @interface THttpRequest : TYHttpRequest 13 | 14 | @property (nonatomic, strong, readonly) TYResponseObject *responseObject; 15 | 16 | @property (nonatomic, strong) NSString *identifier; 17 | 18 | - (instancetype)initWithModelClass:(Class)modelClass; 19 | 20 | + (instancetype)requestWithModelClass:(Class)modelClass; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TResponseObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYResponseObject.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/24. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYResponseObject.h" 10 | #import "TYHttpRequest.h" 11 | 12 | 13 | typedef NS_ENUM(NSInteger, TYStauteCode) { 14 | TYStauteSuccessCode = 200, 15 | }; 16 | 17 | @interface TResponseObject : TYResponseObject 18 | 19 | 20 | //@property (nonatomic, assign) NSUInteger pgIndex;//第几页 21 | //@property (nonatomic, assign) NSUInteger pgSize; 22 | //@property (nonatomic, assign) NSUInteger count;//总消息条数 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /TYHttpManagerDemo.xcodeproj/xcuserdata/tany.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | TYHttpManagerDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 2BF5FA4D1CEEB4640052DF27 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYResponseCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYResponseCache.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/24. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TYResponseCache : NSObject 12 | 13 | - (id )objectForKey:(NSString *)key; 14 | 15 | - (id )objectForKey:(NSString *)key overdueDate:(NSDate *)overdueDate; 16 | 17 | - (void)setObject:(id )object forKey:(NSString *)key; 18 | 19 | - (void)removeObjectForKey:(NSString *)key; 20 | 21 | - (void)removeAllObjects; 22 | 23 | - (void)trimToDate:(NSDate *)date; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/THttpRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // THttpRequest.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/24. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "THttpRequest.h" 10 | 11 | @implementation THttpRequest 12 | 13 | @dynamic responseObject; 14 | 15 | - (instancetype)initWithModelClass:(Class)modelClass 16 | { 17 | if (self = [super init]) { 18 | self.responseParser = [[TResponseObject alloc]initWithModelClass:modelClass]; 19 | } 20 | return self; 21 | } 22 | 23 | + (instancetype)requestWithModelClass:(Class)modelClass 24 | { 25 | return [[self alloc]initWithModelClass:modelClass]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYHttpManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYHttpManager.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/23. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TYRequestProtocol.h" 11 | 12 | @interface TYHttpManager : NSObject 13 | 14 | @property (nonatomic, strong) TYRequstConfigure *requestConfiguration;// session configure 15 | 16 | + (TYHttpManager *)sharedInstance; 17 | 18 | - (void)addRequest:(id)request; 19 | 20 | - (void)cancleRequest:(id)request; 21 | 22 | - (NSString *)buildRequstURL:(id)request; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TCatergoryModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TCatergoryModel.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/24. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TCatergoryData : NSObject 12 | 13 | @property (nonatomic,strong) NSArray *secondary_banners; 14 | 15 | @end 16 | 17 | @interface TCatergoryModel : NSObject 18 | 19 | @property (nonatomic, assign) NSInteger id; 20 | @property (nonatomic, strong) NSString *image_url; 21 | @property (nonatomic, strong) NSString *target_url; 22 | @property (nonatomic, strong) NSString *webp_url; 23 | @property (nonatomic, strong) NSArray *ad_monitors; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TCategoryRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // TCategoryRequest.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/24. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TCategoryRequest.h" 10 | 11 | @implementation TCategoryRequest 12 | 13 | + (instancetype)requestWithGender:(NSString *)gender generation:(NSString *)generation 14 | { 15 | TCategoryRequest *request = [TCategoryRequest requestWithModelClass:[TCatergoryData class]]; 16 | // 可以在appdeleagte 里 设置 TYRequstConfigure baseURL 17 | request.URLString = @"http://api.liwushuo.com/v2/secondary_banners"; 18 | request.parameters = @{@"gender":gender,@"generation":generation};; 19 | return request; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/MBProgressHUD/MBProgressHUD+MJ.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBProgressHUD+MJ.h 3 | // 4 | // Created by mj on 13-4-18. 5 | // Copyright (c) 2013年 itcast. All rights reserved. 6 | // 7 | 8 | #import "MBProgressHUD.h" 9 | 10 | @interface MBProgressHUD (MJ) 11 | + (void)showSuccess:(NSString *)success toView:(UIView *)view; 12 | + (void)showError:(NSString *)error toView:(UIView *)view; 13 | 14 | + (MBProgressHUD *)showMessage:(NSString *)message toView:(UIView *)view; 15 | 16 | + (void)showAlert:(NSString *)alert toView:(UIView *)view afterDelay:(NSTimeInterval)time; 17 | + (void)showAlert:(NSString *)alert afterDelay:(NSTimeInterval)time; 18 | 19 | 20 | + (void)showSuccess:(NSString *)success; 21 | + (void)showError:(NSString *)error; 22 | 23 | + (MBProgressHUD *)showMessage:(NSString *)message; 24 | 25 | + (void)hideHUDForView:(UIView *)view; 26 | + (void)hideHUD; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYResponseObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYResponseObject.h 3 | // LovePlayNews 4 | // 5 | // Created by tany on 16/9/7. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TYHttpRequest.h" 11 | 12 | @interface TYResponseObject : NSObject 13 | 14 | @property (nonatomic, strong) NSString *msg; // 消息 15 | 16 | @property (nonatomic, assign) NSInteger status; //状态码 17 | 18 | @property (nonatomic, strong) id data;// json 或 model数据 19 | 20 | // 需要自己在parseResponse实现模型转换 21 | @property (nonatomic, assign, readonly) Class modelClass; 22 | 23 | // 初始化方法 24 | - (instancetype)initWithModelClass:(Class)modelClass; 25 | 26 | // 验证 27 | - (BOOL)isValidResponse:(id)response request:(TYHttpRequest *)request error:(NSError *__autoreleasing *)error; 28 | 29 | // 解析 返回ResponseObject 30 | - (id)parseResponse:(id)response request:(TYHttpRequest *)request; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYJSONModel/TYPropertyInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYPropertyInfo.h 3 | // TYJSONModelDemo 4 | // 5 | // Created by tany on 16/4/6. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface TYPropertyInfo : NSObject 13 | 14 | //@property (nonatomic, assign, readonly) objc_property_t property; // 属性 15 | 16 | @property (nonatomic, strong, readonly) NSString *propertyName; // 属性名 17 | 18 | @property (nonatomic, assign, readonly) Class typeClass; // 属性class类型 如果属性是基本类型为nil 19 | 20 | @property (nonatomic, assign, readonly) BOOL isCustomFondation; // 是否自定义对象类型 21 | 22 | @property (nonatomic, assign, readonly) SEL setter; // 属性 setter 方法 23 | 24 | @property (nonatomic, assign, readonly) SEL getter; // 属性 getter 方法 25 | 26 | - (instancetype)initWithProperty:(objc_property_t)property; 27 | 28 | // 是否是Foundation对象类型 29 | + (BOOL)isClassFromFoundation:(Class)cls; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYChainRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYChainRequest.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/27. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TYRequestProtocol.h" 11 | 12 | @class TYChainRequest; 13 | typedef void (^TYChainRequestSuccessBlock)(TYChainRequest *request); 14 | typedef void (^TYChainRequestFailureBlock)(TYChainRequest *request,NSError *error); 15 | 16 | @interface TYChainRequest : NSObject 17 | 18 | @property (nonatomic, strong, readonly) NSArray *chainRequstArray; 19 | @property (nonatomic, assign, readonly) NSInteger curRequestIndex; 20 | 21 | @property (nonatomic, copy, readonly) TYChainRequestSuccessBlock successBlock; // 请求成功block 22 | @property (nonatomic, copy, readonly) TYChainRequestFailureBlock failureBlock; // 请求失败block 23 | 24 | - (void)addRequest:(id)request; 25 | 26 | - (void)addRequestArray:(NSArray *)requestArray; 27 | 28 | - (void)cancleRequest:(id)request; 29 | 30 | // 设置回调block 31 | - (void)setRequestSuccessBlock:(TYChainRequestSuccessBlock)successBlock failureBlock:(TYChainRequestFailureBlock)failureBlock; 32 | 33 | - (void)loadWithSuccessBlock:(TYChainRequestSuccessBlock)successBlock failureBlock:(TYChainRequestFailureBlock)failureBlock; 34 | 35 | - (void)load; 36 | 37 | - (void)cancle; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYBatchRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYBatchRequest.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/27. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TYRequestProtocol.h" 11 | 12 | @class TYBatchRequest; 13 | typedef void (^TYBatchRequestSuccessBlock)(TYBatchRequest *request); 14 | typedef void (^TYBatchRequestFailureBlock)(TYBatchRequest *request,NSError *error); 15 | 16 | @interface TYBatchRequest : NSObject 17 | 18 | @property (nonatomic, strong, readonly) NSArray *batchRequstArray; 19 | @property (nonatomic, assign, readonly) NSInteger requestCompleteCount; 20 | 21 | @property (nonatomic, copy, readonly) TYBatchRequestSuccessBlock successBlock; // 请求成功block 22 | @property (nonatomic, copy, readonly) TYBatchRequestFailureBlock failureBlock; // 请求失败block 23 | 24 | - (void)addRequest:(id)request; 25 | 26 | - (void)addRequestArray:(NSArray *)requestArray; 27 | 28 | - (void)cancleRequest:(id)request; 29 | 30 | // 设置回调block 31 | - (void)setRequestSuccessBlock:(TYBatchRequestSuccessBlock)successBlock failureBlock:(TYBatchRequestFailureBlock)failureBlock; 32 | 33 | - (void)loadWithSuccessBlock:(TYBatchRequestSuccessBlock)successBlock failureBlock:(TYBatchRequestFailureBlock)failureBlock; 34 | 35 | - (void)load; 36 | 37 | - (void)cancle; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYHttpRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYHttpRequest.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/23. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYBaseRequest.h" 10 | #import "TYBatchRequest.h" 11 | #import "TYChainRequest.h" 12 | 13 | @class TYHttpRequest; 14 | // 请求数据解析 protocol 15 | @protocol TYHttpResponseParser 16 | 17 | - (BOOL)isValidResponse:(id)response request:(TYHttpRequest *)request error:(NSError *__autoreleasing *)error; 18 | 19 | - (id)parseResponse:(id)response request:(TYHttpRequest *)request; 20 | 21 | @end 22 | 23 | // 请求数据缓存 protocol 24 | @protocol TYHttpResponseCache 25 | 26 | - (void)setObject:(id )object forKey:(NSString *)key; 27 | 28 | - (id )objectForKey:(NSString *)key overdueDate:(NSDate *)overdueDate; 29 | 30 | @end 31 | 32 | @interface TYHttpRequest : TYBaseRequest 33 | 34 | @property (nonatomic, assign, readonly) BOOL responseFromCache; // response是否来自缓存 35 | 36 | // 是否请求缓存的response 默认NO 37 | @property (nonatomic, assign) BOOL requestFromCache; 38 | 39 | // 是否缓存response ,有效的response才会缓存 默认NO 40 | @property (nonatomic, assign) BOOL cacheResponse; 41 | 42 | // 缓存时间 默认7天 43 | @property (nonatomic, assign) NSInteger cacheTimeInSeconds; 44 | 45 | // 缓存忽略的某些Paramters的key 46 | @property (nonatomic, strong) NSArray *cacheIgnoreParamtersKeys; 47 | 48 | @property (nonatomic, strong) id responseParser; // 数据解析 49 | @property (nonatomic, strong) id responseCache; // 数据缓存 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYResponseObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // TYResponseObject.m 3 | // LovePlayNews 4 | // 5 | // Created by tany on 16/9/7. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYResponseObject.h" 10 | 11 | @interface TYResponseObject () 12 | 13 | @property (nonatomic, assign) Class modelClass; 14 | 15 | @end 16 | 17 | @implementation TYResponseObject 18 | 19 | - (instancetype)initWithModelClass:(Class)modelClass 20 | { 21 | if (self = [super init]) { 22 | _modelClass = modelClass; 23 | } 24 | return self; 25 | } 26 | 27 | - (BOOL)isValidResponse:(id)response request:(TYHttpRequest *)request error:(NSError *__autoreleasing *)error 28 | { 29 | if (!response) { 30 | *error = [NSError errorWithDomain:@"response is nil" code: -1 userInfo:nil]; 31 | return NO; 32 | } 33 | 34 | NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)request.dataTask.response; 35 | NSInteger responseStatusCode = [httpResponse statusCode]; 36 | 37 | // StatusCode 38 | if (responseStatusCode < 200 || responseStatusCode > 299) { 39 | *error = [NSError errorWithDomain:@"invalid http request" code: responseStatusCode userInfo:nil]; 40 | return NO; 41 | } 42 | return YES; 43 | } 44 | 45 | - (id)parseResponse:(id)response request:(TYHttpRequest *)request 46 | { 47 | _data = response; 48 | return self; 49 | } 50 | 51 | - (NSString *)description 52 | { 53 | return [NSString stringWithFormat:@"\nstatus:%d\nmsg:%@\n",(int)_status,_msg?_msg : @""]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/AFNetworking/AFNetworking.h: -------------------------------------------------------------------------------- 1 | // AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com/) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | #import 26 | 27 | #ifndef _AFNETWORKING_ 28 | #define _AFNETWORKING_ 29 | 30 | #import "AFURLRequestSerialization.h" 31 | #import "AFURLResponseSerialization.h" 32 | #import "AFSecurityPolicy.h" 33 | 34 | #if !TARGET_OS_WATCH 35 | #import "AFNetworkReachabilityManager.h" 36 | #endif 37 | 38 | #import "AFURLSessionManager.h" 39 | #import "AFHTTPSessionManager.h" 40 | 41 | #endif /* _AFNETWORKING_ */ 42 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIMainStoryboardFile 33 | Main 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYJSONModel/NSObject+TYJSONModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+TYJSONModel.h 3 | // TYJSONModelDemo 4 | // 5 | // Created by tany on 16/4/6. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol TYJSONModel 12 | 13 | @optional 14 | 15 | // 数组[value,value] 或 字典{key: value,key: value} value模型映射类型 16 | + (NSDictionary *)modelClassInArrayOrDictonary; 17 | 18 | // 属性名 - key 映射 19 | + (NSDictionary *)modelPropertyMapper; 20 | 21 | // 忽略某些属性 22 | + (NSArray *)ignoreModelProperties; 23 | 24 | @end 25 | 26 | @interface NSObject (TYJSONModel) 27 | 28 | // json to model 29 | + (instancetype)ty_ModelWithJSON:(id)json; // json: NSString,NSDictionary,NSData 30 | + (instancetype)ty_ModelWithDictonary:(NSDictionary *)dic; 31 | 32 | - (void)ty_SetModelWithDictonary:(NSDictionary *)dic; 33 | 34 | // model to json 35 | - (id)ty_ModelToJSONObject; // array or dic 36 | - (NSData *)ty_ModelToJSONData; 37 | - (NSString *)ty_ModelToJSONString; 38 | - (NSDictionary *)ty_ModelToDictonary; 39 | 40 | // dic array to model array 41 | + (NSArray *)ty_modelArrayWithDictionaryArray:(NSArray *)dicArray; 42 | // model array to dic array 43 | + (NSArray *)ty_dictionaryArrayWithModelArray:(NSArray *)dicArray; 44 | 45 | // NSCoding 46 | - (void)ty_EncodeWithCoder:(NSCoder *)aCoder; 47 | - (instancetype)ty_InitWithCoder:(NSCoder *)aDecoder; 48 | 49 | @end 50 | 51 | 52 | @interface NSArray (TYJSONModel) 53 | 54 | // to model array 55 | - (NSArray *)ty_ModelArrayWithClass:(Class)cls; 56 | 57 | // to dic array 58 | - (NSArray *)ty_ModelArrayToDicArray; 59 | 60 | @end 61 | 62 | @interface NSDictionary (TYJSONModel) 63 | 64 | // to model dictionary 65 | - (NSDictionary *)ty_ModelDictionaryWithClass:(Class)cls; 66 | 67 | // to dictionary 68 | - (NSDictionary *)ty_ModelDictionaryToDictionary; 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYJSONModel/TYClassInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // TYClassInfo.m 3 | // TYJSONModelDemo 4 | // 5 | // Created by tany on 16/4/6. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYClassInfo.h" 10 | 11 | static NSCache *s_classInfoCache; 12 | 13 | @implementation TYClassInfo 14 | 15 | - (instancetype)initWithClass:(Class )class 16 | { 17 | if (!class) { 18 | return nil; 19 | } 20 | 21 | // 取缓存 22 | id cacheInfo = [self objectOnCacheForClass:class]; 23 | if (cacheInfo) { 24 | return cacheInfo; 25 | } 26 | 27 | if (self = [super init]) { 28 | 29 | _cls = class; 30 | 31 | unsigned int propertyCount = 0; 32 | // 获取属性list 33 | objc_property_t *properties = class_copyPropertyList(_cls, &propertyCount); 34 | 35 | if (properties) { 36 | NSMutableDictionary *propertyInfo = [NSMutableDictionary dictionaryWithCapacity:propertyCount]; 37 | 38 | for (unsigned int i = 0; i < propertyCount; i++) { 39 | // 生成属性对象 40 | TYPropertyInfo *info = [[TYPropertyInfo alloc] initWithProperty:properties[i]]; 41 | if (info.propertyName) 42 | // 添加到(属性名 - 属性对象)字典 43 | propertyInfo[info.propertyName] = info; 44 | } 45 | 46 | free(properties); 47 | _propertyInfo = [propertyInfo copy]; 48 | } 49 | } 50 | 51 | // 添加到缓存 52 | [self setObjectToCacheForClass:class]; 53 | 54 | return self; 55 | } 56 | 57 | - (id)objectOnCacheForClass:(Class)class 58 | { 59 | static dispatch_once_t onceToken; 60 | dispatch_once(&onceToken, ^{ 61 | // 设置 class 缓存 62 | s_classInfoCache = [[NSCache alloc]init]; 63 | s_classInfoCache.totalCostLimit = 0.5*1024*1024; 64 | s_classInfoCache.countLimit = 50; 65 | }); 66 | id cacheInfo = [s_classInfoCache objectForKey:class]; 67 | return cacheInfo; 68 | } 69 | 70 | - (void)setObjectToCacheForClass:(Class)class 71 | { 72 | [s_classInfoCache setObject:self forKey:class]; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TResponseObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // TYResponseObject.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/24. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TResponseObject.h" 10 | #import "TYJSONModel.h" 11 | 12 | @implementation TResponseObject 13 | 14 | - (BOOL)isValidResponse:(id)response request:(TYHttpRequest *)request error:(NSError *__autoreleasing *)error 15 | { 16 | if (![super isValidResponse:response request:request error:error]) { 17 | return NO; 18 | } 19 | 20 | // 根据 response 结构 应该为字典 21 | if (![response isKindOfClass:[NSDictionary class]]) { 22 | *error = [NSError errorWithDomain:@"response is invalide, is not NSDictionary" code:-1 userInfo:nil]; 23 | return NO; 24 | } 25 | 26 | // 获取自定义的状态码 27 | NSInteger status = [[response objectForKey:@"code"] integerValue]; 28 | if (status != TYStauteSuccessCode) { 29 | self.status = status; 30 | self.msg = [response objectForKey:@"message"]; 31 | *error = [NSError errorWithDomain:self.msg code:self.status userInfo:nil]; 32 | return NO; 33 | } 34 | 35 | return YES; 36 | } 37 | 38 | - (id)parseResponse:(id)response request:(TYHttpRequest *)request 39 | { 40 | self.status = [[response objectForKey:@"code"] integerValue]; 41 | self.msg = [response objectForKey:@"message"]; 42 | id json = [response objectForKey:@"data"]; 43 | // _pgIndex = [[response objectForKey:@"pgIndex"] integerValue]; 44 | // _pgSize = [[response objectForKey:@"pgSize"] integerValue]; 45 | // _count = [[response objectForKey:@"count"] integerValue]; 46 | 47 | if (self.modelClass) { 48 | if ([json isKindOfClass:[NSDictionary class]]) { 49 | self.data = [[self modelClass] ty_ModelWithDictonary:json]; 50 | }else if ([json isKindOfClass:[NSArray class]]) { 51 | self.data = [[self modelClass] ty_modelArrayWithDictionaryArray:json]; 52 | } 53 | }else { 54 | self.data = json; 55 | } 56 | return self; 57 | } 58 | 59 | //- (void)dealloc 60 | //{ 61 | // NSLog(@"%@%s",NSStringFromClass([self class]),__func__); 62 | //} 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/20. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYRequestProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYRequestProtocol.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/20. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TYRequstConfigure.h" 11 | 12 | typedef NS_ENUM(NSUInteger, TYRequestMethod) { 13 | TYRequestMethodGet, 14 | TYRequestMethodPost, 15 | TYRequestMethodHead, 16 | TYRequestMethodPut, 17 | TYRequestMethodDelete, 18 | TYRequestMethodPatch 19 | }; 20 | 21 | typedef NS_ENUM(NSInteger , TYRequestSerializerType) { 22 | TYRequestSerializerTypeHTTP, 23 | TYRequestSerializerTypeJSON, 24 | TYRequestSerializerTypeString 25 | }; 26 | 27 | typedef NS_ENUM(NSUInteger, TYRequestState) { 28 | TYRequestStateReady, 29 | TYRequestStateLoading, 30 | TYRequestStateCancle, 31 | TYRequestStateFinish, 32 | TYRequestStateError 33 | }; 34 | 35 | @protocol AFMultipartFormData; // need import afnetwork 36 | typedef void(^AFProgressBlock)(NSProgress * progress); 37 | typedef void(^AFConstructingBodyBlock)(id formData); 38 | 39 | 40 | @protocol TYRequestProtocol; 41 | @protocol TYRequestDelegate 42 | 43 | @optional 44 | 45 | - (void)requestDidFinish:(id)request; 46 | 47 | - (void)requestDidFail:(id)request error:(NSError *)error; 48 | 49 | @end 50 | 51 | 52 | @protocol TYRequestProtocol 53 | 54 | @property (nonatomic, weak) NSURLSessionTask *dataTask; 55 | 56 | @property (nonatomic, assign, readonly) TYRequestState state; 57 | @property (nonatomic, strong, readonly) id responseObject; 58 | 59 | @property (nonatomic, weak) id delegate; // 请求代理 60 | @property (nonatomic, strong) id embedAccesory; // 嵌入请求代理 注意strong 61 | 62 | // baseURL 如果为空,则为全局或者本类requestConfigure.baseURL 63 | - (NSString *)baseURL; 64 | 65 | // 请求的URLString,或者 URL path 66 | - (NSString *)URLString; 67 | 68 | // 请求参数 69 | - (NSDictionary *)parameters; 70 | 71 | // 请求的方法 默认get 72 | - (TYRequestMethod)method; 73 | 74 | // request configure 75 | - (TYRequstConfigure *)configuration; 76 | 77 | // 在HTTP报头添加的自定义参数 78 | - (NSDictionary *)headerFieldValues; 79 | 80 | // 请求的连接超时时间,默认为60秒 81 | - (NSTimeInterval)timeoutInterval; 82 | 83 | // 缓存策略 84 | - (NSURLRequestCachePolicy) cachePolicy; 85 | 86 | // 设置请求格式 默认 JSON 87 | - (TYRequestSerializerType)serializerType; 88 | 89 | // 返回进度block 90 | - (AFProgressBlock)progressBlock; 91 | 92 | // 返回post组装body block 93 | - (AFConstructingBodyBlock)constructingBodyBlock; 94 | 95 | // 处理请求数据, 如果error == nil ,请求成功 96 | - (void)requestDidResponse:(id)responseObject error:(NSError *)error; 97 | 98 | // 请求 99 | - (void)load; 100 | 101 | // 取消 102 | - (void)cancle; 103 | 104 | @end 105 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYBaseRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // TYBaseRequest.h 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/23. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYRequestProtocol.h" 10 | 11 | typedef void (^TYRequestSuccessBlock)(id request); 12 | typedef void (^TYRequestFailureBlock)(id request,NSError *error); 13 | 14 | @protocol TYRequestOverride 15 | 16 | // 收到请求数据, 如果error == nil 17 | - (void)requestDidResponse:(id)responseObject error:(NSError *)error; 18 | 19 | // 验证请求数据 20 | - (BOOL)validResponseObject:(id)responseObject error:(NSError *__autoreleasing *)error; 21 | 22 | // 请求成功 23 | - (void)requestDidFinish; 24 | 25 | // 请求失败 26 | - (void)requestDidFailWithError:(NSError* )error; 27 | 28 | @end 29 | 30 | @interface TYBaseRequest : NSObject 31 | 32 | #pragma mark - request 33 | @property (nonatomic, weak) NSURLSessionDataTask *dataTask; 34 | @property (nonatomic, assign, readonly) TYRequestState state; 35 | @property (nonatomic, strong, readonly) id responseObject; 36 | 37 | @property (nonatomic, weak) id delegate; // 请求代理 38 | @property (nonatomic, strong) id embedAccesory; // 完成请求代理 后调用 注意strong 39 | 40 | @property (nonatomic, assign) BOOL asynCompleteQueue; // 在异步线程中回调 默认NO 41 | 42 | #pragma mark - block 43 | @property (nonatomic, copy, readonly) TYRequestSuccessBlock successBlock; // 请求成功block 44 | @property (nonatomic, copy, readonly) TYRequestFailureBlock failureBlock; // 请求失败block 45 | 46 | @property (nonatomic, copy) AFProgressBlock progressBlock;// 请求进度block 47 | @property (nonatomic, copy) AFConstructingBodyBlock constructingBodyBlock;// post请求组装body block 48 | 49 | #pragma mark - request params 50 | // baseURL 如果为空,则为全局或者本类requestConfigure.baseURL 51 | @property (nonatomic, strong) NSString *baseURL; 52 | 53 | // 请求的URLString 或者 URL path 54 | @property (nonatomic, strong) NSString *URLString; 55 | 56 | // 请求方法 默认GET 57 | @property (nonatomic, assign) TYRequestMethod method; 58 | 59 | // 请求参数 60 | @property (nonatomic, strong) NSDictionary *parameters; 61 | 62 | // 设置请求格式 默认 JSON 63 | @property (nonatomic, assign) TYRequestSerializerType serializerType; 64 | 65 | // 请求缓存策略 66 | @property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy; 67 | 68 | // 请求的连接超时时间,默认为60秒 69 | @property (nonatomic, assign) NSTimeInterval timeoutInterval; 70 | 71 | // 请求设置 默认 使用 全局的requestConfigure 72 | @property (nonatomic, strong) TYRequstConfigure *configuration; 73 | 74 | // 在HTTP报头添加的自定义参数 75 | @property (nonatomic, strong) NSDictionary *headerFieldValues; 76 | 77 | // 请求 78 | - (void)load; 79 | 80 | // 设置回调block 81 | - (void)setRequestSuccessBlock:(TYRequestSuccessBlock)successBlock failureBlock:(TYRequestFailureBlock)failureBlock; 82 | 83 | - (void)loadWithSuccessBlock:(TYRequestSuccessBlock)successBlock failureBlock:(TYRequestFailureBlock)failureBlock; 84 | 85 | // 取消 86 | - (void)cancle; 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/MBProgressHUD/MBProgressHUD+MJ.m: -------------------------------------------------------------------------------- 1 | // 2 | // MBProgressHUD+MJ.m 3 | // 4 | // Created by mj on 13-4-18. 5 | // Copyright (c) 2013年 itcast. All rights reserved. 6 | // 7 | 8 | #import "MBProgressHUD+MJ.h" 9 | 10 | @implementation MBProgressHUD (MJ) 11 | #pragma mark 显示信息 12 | + (void)show:(NSString *)text icon:(NSString *)icon view:(UIView *)view afterDelay:(NSTimeInterval)time 13 | { 14 | if (view == nil) view = [[UIApplication sharedApplication].windows lastObject]; 15 | [MBProgressHUD hideAllHUDsForView:view animated:NO]; 16 | // 快速显示一个提示信息 17 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; 18 | hud.labelText = text; 19 | hud.margin = 12.0f; 20 | // 设置图片 21 | hud.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"MBProgressHUD.bundle/%@", icon]]]; 22 | // 再设置模式 23 | hud.mode = MBProgressHUDModeCustomView; 24 | 25 | // 隐藏时候从父控件中移除 26 | hud.removeFromSuperViewOnHide = YES; 27 | hud.square = NO; 28 | // 1秒之后再消失 29 | [hud hide:YES afterDelay:time]; 30 | } 31 | 32 | #pragma mark 显示错误信息 33 | + (void)showAlert:(NSString *)alert toView:(UIView *)view afterDelay:(NSTimeInterval)time 34 | { 35 | [self show:alert icon:@"info.png" view:view afterDelay:time]; 36 | } 37 | 38 | + (void)showAlert:(NSString *)alert afterDelay:(NSTimeInterval)time 39 | { 40 | [self show:alert icon:@"info.png" view:nil afterDelay:time]; 41 | } 42 | 43 | + (void)showError:(NSString *)error toView:(UIView *)view{ 44 | [self show:error icon:@"error.png" view:view afterDelay:1.0]; 45 | } 46 | 47 | + (void)showSuccess:(NSString *)success toView:(UIView *)view 48 | { 49 | [self show:success icon:@"success.png" view:view afterDelay:1.0]; 50 | } 51 | 52 | #pragma mark 显示一些信息 53 | + (MBProgressHUD *)showMessage:(NSString *)message toView:(UIView *)view { 54 | if (view == nil) view = [[UIApplication sharedApplication].windows lastObject]; 55 | [MBProgressHUD hideAllHUDsForView:view animated:NO]; 56 | // 快速显示一个提示信息 57 | MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; 58 | hud.labelText = message; 59 | // 隐藏时候从父控件中移除 60 | hud.removeFromSuperViewOnHide = YES; 61 | // YES代表需要蒙版效果 62 | hud.dimBackground = NO; 63 | return hud; 64 | } 65 | 66 | + (void)showSuccess:(NSString *)success 67 | { 68 | [self showSuccess:success toView:nil]; 69 | } 70 | 71 | + (void)showError:(NSString *)error 72 | { 73 | [self showError:error toView:nil]; 74 | } 75 | 76 | + (void)showAlert:(NSString *)message 77 | { 78 | [self showAlert:message afterDelay:1.0]; 79 | } 80 | 81 | + (MBProgressHUD *)showMessage:(NSString *)message 82 | { 83 | return [self showMessage:message toView:nil]; 84 | } 85 | 86 | + (void)hideHUDForView:(UIView *)view 87 | { 88 | if (view == nil) view = [[UIApplication sharedApplication].windows lastObject]; 89 | [self hideHUDForView:view animated:YES]; 90 | } 91 | 92 | + (void)hideHUD 93 | { 94 | [self hideHUDForView:nil]; 95 | } 96 | @end 97 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYBatchRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // TYBatchRequest.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/27. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYBatchRequest.h" 10 | 11 | @interface TYBatchRequest () 12 | @property (nonatomic, strong) NSMutableArray *batchRequstArray; 13 | @property (nonatomic, assign) NSInteger requestCompleteCount; 14 | @property (nonatomic, assign) BOOL isLoading; 15 | @end 16 | 17 | @implementation TYBatchRequest 18 | 19 | - (instancetype)init 20 | { 21 | if (self = [super init]) { 22 | _batchRequstArray = [NSMutableArray array]; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)addRequest:(id)request 28 | { 29 | if (_isLoading) { 30 | NSLog(@"TYBatchRequest is Running,can't add request"); 31 | return; 32 | } 33 | request.embedAccesory = self; 34 | [_batchRequstArray addObject:request]; 35 | } 36 | 37 | - (void)addRequestArray:(NSArray *)requestArray 38 | { 39 | for (id request in requestArray) { 40 | if ([request conformsToProtocol:@protocol(TYRequestProtocol) ]) { 41 | [self addRequest:request]; 42 | } 43 | } 44 | } 45 | 46 | - (void)cancleRequest:(id)request 47 | { 48 | request.embedAccesory = nil; 49 | [request cancle]; 50 | [_batchRequstArray removeObject:request]; 51 | } 52 | 53 | - (void)setRequestSuccessBlock:(TYBatchRequestSuccessBlock)successBlock failureBlock:(TYBatchRequestFailureBlock)failureBlock 54 | { 55 | _successBlock = successBlock; 56 | _failureBlock = failureBlock; 57 | 58 | } 59 | 60 | - (void)loadWithSuccessBlock:(TYBatchRequestSuccessBlock)successBlock failureBlock:(TYBatchRequestFailureBlock)failureBlock 61 | { 62 | [self setRequestSuccessBlock:successBlock failureBlock:failureBlock]; 63 | 64 | [self load]; 65 | } 66 | 67 | - (void)load{ 68 | if (_isLoading ||_batchRequstArray.count == 0) { 69 | return; 70 | } 71 | _isLoading = YES; 72 | _requestCompleteCount = 0; 73 | for (id request in _batchRequstArray) { 74 | [request load]; 75 | } 76 | } 77 | 78 | - (void)cancle 79 | { 80 | for (id request in _batchRequstArray) { 81 | request.embedAccesory = nil; 82 | [request cancle]; 83 | } 84 | [_batchRequstArray removeAllObjects]; 85 | _requestCompleteCount = 0; 86 | _isLoading = NO; 87 | } 88 | 89 | #pragma mark - delegate 90 | 91 | - (void)requestDidFinish:(id)request 92 | { 93 | NSInteger index = [_batchRequstArray indexOfObject:request]; 94 | if (index != NSNotFound) { 95 | ++_requestCompleteCount; 96 | } 97 | 98 | if (_requestCompleteCount == _batchRequstArray.count) { 99 | if (_successBlock) { 100 | _successBlock(self); 101 | } 102 | [_batchRequstArray removeAllObjects]; 103 | _isLoading = NO; 104 | } 105 | } 106 | 107 | - (void)requestDidFail:(id)request error:(NSError *)error 108 | { 109 | if (_failureBlock) { 110 | _failureBlock(self,error); 111 | } 112 | [_batchRequstArray removeAllObjects]; 113 | _isLoading = NO; 114 | 115 | } 116 | 117 | - (void)clearBlocks 118 | { 119 | _successBlock = nil; 120 | _failureBlock = nil; 121 | } 122 | 123 | - (void)dealloc 124 | { 125 | [self clearBlocks]; 126 | } 127 | 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /TYHttpManagerDemo.xcodeproj/xcuserdata/tany.xcuserdatad/xcschemes/TYHttpManagerDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYChainRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // TYChainRequest.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/27. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYChainRequest.h" 10 | 11 | @interface TYChainRequest () 12 | @property (nonatomic, strong) NSMutableArray *chainRequstArray; 13 | @property (nonatomic, assign) NSInteger curRequestIndex; 14 | @property (nonatomic, assign) BOOL isLoading; 15 | @end 16 | 17 | @implementation TYChainRequest 18 | 19 | - (instancetype)init 20 | { 21 | if (self = [super init]) { 22 | _chainRequstArray = [NSMutableArray array]; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)addRequest:(id)request 28 | { 29 | if (_isLoading) { 30 | NSLog(@"TYChainRequest is Running,can't add request"); 31 | return; 32 | } 33 | request.embedAccesory = self; 34 | [_chainRequstArray addObject:request]; 35 | } 36 | 37 | - (void)addRequestArray:(NSArray *)requestArray 38 | { 39 | for (id request in requestArray) { 40 | if ([request conformsToProtocol:@protocol(TYRequestProtocol) ]) { 41 | [self addRequest:request]; 42 | } 43 | } 44 | } 45 | 46 | - (void)cancleRequest:(id)request 47 | { 48 | request.embedAccesory = nil; 49 | [request cancle]; 50 | [_chainRequstArray removeObject:request]; 51 | } 52 | 53 | - (void)load 54 | { 55 | if (_isLoading ||_chainRequstArray.count == 0) { 56 | return; 57 | } 58 | 59 | _isLoading = YES; 60 | [self loadNextChainRequestWithCurIndex:-1]; 61 | } 62 | 63 | - (void)setRequestSuccessBlock:(TYChainRequestSuccessBlock)successBlock failureBlock:(TYChainRequestFailureBlock)failureBlock 64 | { 65 | _successBlock = successBlock; 66 | _failureBlock = failureBlock; 67 | 68 | } 69 | 70 | - (void)loadWithSuccessBlock:(TYChainRequestSuccessBlock)successBlock failureBlock:(TYChainRequestFailureBlock)failureBlock 71 | { 72 | [self setRequestSuccessBlock:successBlock failureBlock:failureBlock]; 73 | 74 | [self load]; 75 | } 76 | 77 | - (void)cancle 78 | { 79 | for (id request in _chainRequstArray) { 80 | request.embedAccesory = nil; 81 | } 82 | 83 | if (_curRequestIndex >= 0 && _curRequestIndex < _chainRequstArray.count) { 84 | id request = _chainRequstArray[_curRequestIndex]; 85 | [request cancle]; 86 | } 87 | 88 | [_chainRequstArray removeAllObjects]; 89 | _curRequestIndex = 0; 90 | _isLoading = NO; 91 | } 92 | 93 | - (void)loadNextChainRequestWithCurIndex:(NSInteger)index 94 | { 95 | NSInteger count = _chainRequstArray.count; 96 | if (index >= -1 && index < count - 1) { 97 | _curRequestIndex = index + 1; 98 | id request = _chainRequstArray[_curRequestIndex]; 99 | [request load]; 100 | }else { 101 | if (_successBlock) { 102 | _successBlock(self); 103 | } 104 | [_chainRequstArray removeAllObjects]; 105 | _isLoading = NO; 106 | } 107 | } 108 | 109 | #pragma mark - delegate 110 | 111 | - (void)requestDidFinish:(id)request 112 | { 113 | NSInteger index = [_chainRequstArray indexOfObject:request]; 114 | if (index != NSNotFound) { 115 | [self loadNextChainRequestWithCurIndex:index]; 116 | } 117 | } 118 | 119 | - (void)requestDidFail:(id)request error:(NSError *)error 120 | { 121 | if (_failureBlock) { 122 | _failureBlock(self,error); 123 | } 124 | [_chainRequstArray removeAllObjects]; 125 | _isLoading = NO; 126 | 127 | } 128 | 129 | - (void)clearBlocks 130 | { 131 | _successBlock = nil; 132 | _failureBlock = nil; 133 | } 134 | 135 | - (void)dealloc 136 | { 137 | [self clearBlocks]; 138 | } 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYBaseRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // TYBaseRequest.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/23. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYBaseRequest.h" 10 | #import "TYHttpManager.h" 11 | 12 | @interface TYBaseRequest () 13 | @property (nonatomic, copy) TYRequestSuccessBlock successBlock; 14 | @property (nonatomic, copy) TYRequestFailureBlock failureBlock; 15 | 16 | @property (nonatomic, assign) TYRequestState state; 17 | @property (nonatomic, strong) id responseObject; 18 | @end 19 | 20 | @implementation TYBaseRequest 21 | 22 | -(instancetype)init 23 | { 24 | if (self = [super init]) { 25 | _method = TYRequestMethodGet; 26 | _serializerType = TYRequestSerializerTypeJSON; 27 | _timeoutInterval = 60; 28 | } 29 | return self; 30 | } 31 | 32 | #pragma mark - load request 33 | 34 | // 请求 35 | - (void)load 36 | { 37 | [[TYHttpManager sharedInstance] addRequest:self]; 38 | _state = TYRequestStateLoading; 39 | } 40 | 41 | // 取消 42 | - (void)cancle 43 | { 44 | [_dataTask cancel]; 45 | [self clearRequestBlock]; 46 | _delegate = nil; 47 | _state = TYRequestStateCancle; 48 | } 49 | 50 | - (void)setRequestSuccessBlock:(TYRequestSuccessBlock)successBlock failureBlock:(TYRequestFailureBlock)failureBlock 51 | { 52 | _successBlock = successBlock; 53 | _failureBlock = failureBlock; 54 | 55 | } 56 | 57 | - (void)loadWithSuccessBlock:(TYRequestSuccessBlock)successBlock failureBlock:(TYRequestFailureBlock)failureBlock 58 | { 59 | [self setRequestSuccessBlock:successBlock failureBlock:failureBlock]; 60 | 61 | [self load]; 62 | } 63 | 64 | #pragma mark - call delegate , block 65 | 66 | // 收到数据 67 | - (void)requestDidResponse:(id)responseObject error:(NSError *)error 68 | { 69 | if (error) { 70 | [self requestDidFailWithError:error]; 71 | }else { 72 | if ([self validResponseObject:responseObject error:&error]){ 73 | [self requestDidFinish]; 74 | }else{ 75 | [self requestDidFailWithError:error]; 76 | } 77 | } 78 | } 79 | 80 | // 验证数据 81 | - (BOOL)validResponseObject:(id)responseObject error:(NSError *__autoreleasing *)error 82 | { 83 | _responseObject = responseObject; 84 | return _responseObject ? YES : NO; 85 | } 86 | 87 | // 请求成功 88 | - (void)requestDidFinish 89 | { 90 | _state = TYRequestStateFinish; 91 | 92 | void (^finishBlock)() = ^{ 93 | if ([_delegate respondsToSelector:@selector(requestDidFinish:)]) { 94 | [_delegate requestDidFinish:self]; 95 | } 96 | 97 | if (_successBlock) { 98 | _successBlock(self); 99 | } 100 | 101 | if (_embedAccesory && [_embedAccesory respondsToSelector:@selector(requestDidFinish:)]) { 102 | [_embedAccesory requestDidFinish:self]; 103 | } 104 | }; 105 | 106 | if (_asynCompleteQueue) { 107 | finishBlock(); 108 | }else { 109 | dispatch_async(dispatch_get_main_queue(),finishBlock); 110 | } 111 | } 112 | 113 | // 请求失败 114 | - (void)requestDidFailWithError:(NSError* )error 115 | { 116 | _state = TYRequestStateError; 117 | 118 | void (^failBlock)() = ^{ 119 | if ([_delegate respondsToSelector:@selector(requestDidFail:error:)]) { 120 | [_delegate requestDidFail:self error:error]; 121 | } 122 | 123 | if (_failureBlock) { 124 | _failureBlock(self,error); 125 | } 126 | 127 | if (_embedAccesory && [_embedAccesory respondsToSelector:@selector(requestDidFail:error:)]) { 128 | [_embedAccesory requestDidFail:self error:error]; 129 | } 130 | }; 131 | 132 | if (_asynCompleteQueue) { 133 | failBlock(); 134 | }else { 135 | dispatch_async(dispatch_get_main_queue(),failBlock); 136 | } 137 | } 138 | // 清除block引用 139 | - (void)clearRequestBlock 140 | { 141 | _successBlock = nil; 142 | _failureBlock = nil; 143 | _progressBlock = nil; 144 | _constructingBodyBlock = nil; 145 | } 146 | 147 | - (void)dealloc 148 | { 149 | [self clearRequestBlock]; 150 | [_dataTask cancel]; 151 | _delegate = nil; 152 | } 153 | 154 | @end 155 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYJSONModel/TYPropertyInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // TYPropertyInfo.m 3 | // TYJSONModelDemo 4 | // 5 | // Created by tany on 16/4/6. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYPropertyInfo.h" 10 | #import 11 | 12 | @implementation TYPropertyInfo 13 | 14 | - (instancetype)initWithProperty:(objc_property_t)property 15 | { 16 | if (!property) { 17 | return nil; 18 | } 19 | 20 | if (self = [super init]) { 21 | 22 | //_property = property; 23 | // 获取属性名 24 | const char *cPropertyName = property_getName(property); 25 | if (cPropertyName) { 26 | _propertyName = [NSString stringWithUTF8String:cPropertyName]; 27 | } 28 | 29 | BOOL readOnlyProperty = NO; 30 | unsigned int attrCount; 31 | // 获取属性的属性list 32 | objc_property_attribute_t *attrs = property_copyAttributeList(property, &attrCount); 33 | for (unsigned int idx = 0; idx < attrCount; ++idx) { 34 | switch (attrs[idx].name[0]) { 35 | case 'T': // 属性 36 | if (attrs[idx].name[0] == 'T') { 37 | size_t len = strlen(attrs[idx].value); 38 | if (len>3) { 39 | char name[len - 2]; 40 | name[len - 3] = '\0'; 41 | memcpy(name, attrs[idx].value + 2, len - 3); 42 | // 获取 属性类型名 (基本类型 _typeClass = ni ) 43 | _typeClass = objc_getClass(name); 44 | } 45 | } 46 | break; 47 | case 'R': 48 | readOnlyProperty = YES; 49 | break; 50 | case 'G': // 自定义getter方法 51 | if (attrs[idx].value) { 52 | _getter = NSSelectorFromString([NSString stringWithUTF8String:attrs[idx].value]); 53 | } 54 | break; 55 | case 'S': // 自定义setter方法 56 | if (attrs[idx].value) { 57 | _setter = NSSelectorFromString([NSString stringWithUTF8String:attrs[idx].value]); 58 | } 59 | break; 60 | 61 | default: 62 | break; 63 | } 64 | } 65 | 66 | if (attrs) { 67 | free(attrs); 68 | } 69 | 70 | if (_typeClass) { 71 | // 判断是否自定义对象类型 72 | _isCustomFondation = ![[self class] isClassFromFoundation:_typeClass]; 73 | } 74 | 75 | if (_typeClass && _propertyName.length > 0) { 76 | // 如果是对象类型 生成 getter setter 方法 77 | if (!_getter) { 78 | _getter = NSSelectorFromString(_propertyName); 79 | } 80 | if (!_setter && !readOnlyProperty) { 81 | _setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:", [_propertyName substringToIndex:1].uppercaseString, [_propertyName substringFromIndex:1]]); 82 | } 83 | } 84 | 85 | } 86 | return self; 87 | } 88 | 89 | // 是否是Foundation对象类型 90 | + (BOOL)isClassFromFoundation:(Class)class 91 | { 92 | if (class == [NSString class] || class == [NSObject class]) 93 | return YES; 94 | 95 | static NSArray *s_foundations; 96 | static dispatch_once_t onceToken; 97 | dispatch_once(&onceToken, ^{ 98 | s_foundations = @[[NSURL class], 99 | [NSDate class], 100 | [NSValue class], 101 | [NSData class], 102 | [NSError class], 103 | [NSArray class], 104 | [NSDictionary class], 105 | [NSString class], 106 | [NSAttributedString class]]; 107 | }); 108 | 109 | BOOL result = NO; 110 | for (Class foundationClass in s_foundations) { 111 | if ([class isSubclassOfClass:foundationClass]) { 112 | result = YES; 113 | break; 114 | } 115 | } 116 | 117 | return result; 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYHttpRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // TYHttpRequest.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/23. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYHttpRequest.h" 10 | #import "TYResponseCache.h" 11 | #import "TYHttpManager.h" 12 | 13 | @interface TYResponseCache () 14 | @end 15 | 16 | @implementation TYHttpRequest 17 | 18 | - (instancetype)init 19 | { 20 | if (self = [super init]) { 21 | _cacheTimeInSeconds = 60*60*24*7; 22 | } 23 | return self; 24 | } 25 | 26 | #pragma mark - load reqeust 27 | 28 | - (id)responseCache 29 | { 30 | if (_responseCache == nil) { 31 | _responseCache = [[TYResponseCache alloc]init]; 32 | } 33 | return _responseCache; 34 | } 35 | 36 | - (void)load 37 | { 38 | _responseFromCache = NO; 39 | if (_requestFromCache && _cacheTimeInSeconds >= 0) { 40 | // 从缓存中获取 41 | [self loadResponseFromCache]; 42 | } 43 | //NSLog(@"responseFromCache %d",_responseFromCache); 44 | if (!_responseFromCache) { 45 | // 请求数据 46 | [super load]; 47 | } 48 | } 49 | 50 | // 从缓存中获取数据 51 | - (void)loadResponseFromCache 52 | { 53 | id responseCache = [self responseCache]; 54 | 55 | if (!responseCache) { 56 | return; 57 | } 58 | 59 | // 计算过期时间 60 | double pastTimeInterval = [[NSDate date] timeIntervalSince1970]-[self cacheTimeInSeconds]; 61 | NSDate *pastDate = [NSDate dateWithTimeIntervalSince1970:pastTimeInterval]; 62 | 63 | // 根据URL 和 过期时间 获取缓存 64 | NSString *urlKey = [self serializeURLKey]; 65 | id responseObject = [responseCache objectForKey:urlKey overdueDate:pastDate]; 66 | if (responseObject) { 67 | // 获取到缓存 68 | _responseFromCache = YES; 69 | [self requestDidResponse:responseObject error:nil]; 70 | } 71 | } 72 | 73 | // 验证缓存 74 | - (BOOL)validResponseObject:(id)responseObject error:(NSError *__autoreleasing *)error 75 | { 76 | id responseParser = [self responseParser]; 77 | if (responseParser == nil) { 78 | [self cacheRequsetResponse:responseObject]; 79 | return [super validResponseObject:responseObject error:error]; 80 | } 81 | 82 | if (_responseFromCache || [responseParser isValidResponse:responseObject request:self error:error]) { 83 | // 有效的数据 才可以缓存 84 | [self cacheRequsetResponse:responseObject]; 85 | // 验证后 解析数据 86 | id responseParsedObject = [responseParser parseResponse:responseObject request:self]; 87 | return [super validResponseObject:responseParsedObject error:error]; 88 | }else { 89 | return NO; 90 | } 91 | } 92 | 93 | #pragma mark - private 94 | 95 | - (void)cacheRequsetResponse:(id)responseObject 96 | { 97 | if (responseObject && _cacheResponse && !_responseFromCache) { 98 | NSString *urlKey = [self serializeURLKey]; 99 | [[self responseCache]setObject:responseObject forKey:urlKey]; 100 | } 101 | } 102 | // 拼装url key 103 | - (NSString *)serializeURLKey 104 | { 105 | NSDictionary *paramters = [self parameters]; 106 | NSArray *ignoreParamterKeys = [self cacheIgnoreParamtersKeys]; 107 | if (ignoreParamterKeys) { 108 | NSMutableDictionary *fiterParamters = [NSMutableDictionary dictionaryWithDictionary:paramters]; 109 | [fiterParamters removeObjectsForKeys:ignoreParamterKeys]; 110 | paramters = fiterParamters; 111 | } 112 | NSString *URLString = [[TYHttpManager sharedInstance]buildRequstURL:self]; 113 | return [URLString stringByAppendingString:[self serializeParams:paramters]]; 114 | } 115 | 116 | // 拼接params 117 | - (NSString *)serializeParams:(NSDictionary *)params { 118 | NSMutableArray *parts = [NSMutableArray array]; 119 | [params enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { 120 | NSString *encodedKey = [key stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; 121 | NSString *encodedValue = [obj.description stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; 122 | NSString *part = [NSString stringWithFormat: @"%@=%@", encodedKey, encodedValue]; 123 | [parts addObject: part]; 124 | }]; 125 | NSString *queryString = [parts componentsJoinedByString: @"&"]; 126 | return queryString?[NSString stringWithFormat:@"?%@", queryString]:@""; 127 | } 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/20. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "MBProgressHUD+MJ.h" 11 | #import "TCategoryRequest.h" 12 | #import "TYChainRequest.h" 13 | #import "TYBatchRequest.h" 14 | 15 | @interface ViewController () 16 | @property (nonatomic, weak) THttpRequest *request; 17 | 18 | @end 19 | 20 | @implementation ViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view, typically from a nib. 25 | } 26 | 27 | // 请求 使用block 28 | - (IBAction)requestBlockAction:(id)sender { 29 | 30 | [MBProgressHUD showMessage:@"加载中..." toView:self.view]; 31 | 32 | // request 使用继承 33 | [_request cancle]; 34 | _request = [TCategoryRequest requestWithGender:@"1" generation:@"1"]; 35 | // 缓存数据 36 | _request.requestFromCache = YES; 37 | _request.cacheResponse = YES; 38 | 39 | [_request loadWithSuccessBlock:^(TCategoryRequest *request) { 40 | NSLog(@"%@ data:%@",request.responseObject,request.responseObject.data); 41 | [MBProgressHUD showSuccess:@"加载成功!" toView:self.view]; 42 | } failureBlock:^(TCategoryRequest *request, NSError *error) { 43 | [MBProgressHUD showError:@"加载失败!" toView:self.view]; 44 | }]; 45 | } 46 | 47 | // 请求 使用delegate 48 | - (IBAction)requestDelegateAction:(id)sender { 49 | 50 | [MBProgressHUD showMessage:@"加载中..." toView:self.view]; 51 | 52 | // 不用继承 直接使用request 53 | THttpRequest *request = [THttpRequest requestWithModelClass:[TCatergoryData class]]; 54 | // 可以在appdeleagte 里 设置 TYRequstConfigure baseURL 55 | request.URLString = @"http://api.liwushuo.com/v2/secondary_banners"; 56 | request.parameters = @{@"gender":@"1",@"generation":@"1"}; 57 | request.delegate = self; 58 | [request load]; 59 | } 60 | 61 | - (IBAction)chainRquestAction:(id)sender { 62 | [MBProgressHUD showMessage:@"加载中..." toView:self.view]; 63 | 64 | THttpRequest *request1 = [self reuqetWithidentifer:@"11111"]; 65 | THttpRequest *request2 = [self reuqetWithidentifer:@"22222"]; 66 | THttpRequest *request3 = [self reuqetWithidentifer:@"33333"]; 67 | THttpRequest *request4 = [self reuqetWithidentifer:@"44444"]; 68 | THttpRequest *request5 = [self reuqetWithidentifer:@"55555"]; 69 | 70 | TYChainRequest *chainRequest = [[TYChainRequest alloc]init]; 71 | [chainRequest addRequest:request1]; 72 | [chainRequest addRequest:request2]; 73 | [chainRequest addRequest:request3]; 74 | [chainRequest addRequest:request4]; 75 | [chainRequest addRequest:request5]; 76 | 77 | [chainRequest loadWithSuccessBlock:^(TYChainRequest *request) { 78 | // TYChainRequest 79 | [MBProgressHUD showSuccess:@"chainRequest 加载成功!" toView:self.view]; 80 | } failureBlock:^(TYChainRequest *request, NSError *error) { 81 | // TYChainRequest 82 | [MBProgressHUD showError:@"chainRequest 加载失败!" toView:self.view]; 83 | }]; 84 | } 85 | 86 | - (IBAction)batchRequestAction:(id)sender { 87 | [MBProgressHUD showMessage:@"加载中..." toView:self.view]; 88 | 89 | THttpRequest *request1 = [self reuqetWithidentifer:@"11111"]; 90 | THttpRequest *request2 = [self reuqetWithidentifer:@"22222"]; 91 | THttpRequest *request3 = [self reuqetWithidentifer:@"33333"]; 92 | THttpRequest *request4 = [self reuqetWithidentifer:@"44444"]; 93 | THttpRequest *request5 = [self reuqetWithidentifer:@"55555"]; 94 | 95 | TYBatchRequest *batchRequest = [[TYBatchRequest alloc]init]; 96 | [batchRequest addRequest:request1]; 97 | [batchRequest addRequest:request2]; 98 | [batchRequest addRequest:request3]; 99 | [batchRequest addRequest:request4]; 100 | [batchRequest addRequest:request5]; 101 | 102 | [batchRequest loadWithSuccessBlock:^(TYBatchRequest *request) { 103 | // batchRequest 104 | [MBProgressHUD showSuccess:@"batchRequest 加载成功!" toView:self.view]; 105 | } failureBlock:^(TYBatchRequest *request, NSError *error) { 106 | // batchRequest 107 | [MBProgressHUD showError:@"batchRequest 加载失败!" toView:self.view]; 108 | }]; 109 | 110 | } 111 | 112 | - (THttpRequest *)reuqetWithidentifer:(NSString *)identifer 113 | { 114 | THttpRequest *request = [TCategoryRequest requestWithGender:@"1" generation:@"1"]; 115 | request.identifier = identifer; 116 | // 缓存数据 117 | // request.requestFromCache = YES; 118 | // request.cacheResponse = YES; 119 | 120 | [request setRequestSuccessBlock:^(TCategoryRequest *request) { 121 | NSLog(@"请求成功 request id %@",request.identifier); 122 | } failureBlock:^(TCategoryRequest *request, NSError *error) { 123 | NSLog(@"请求失败 request id %@",request.identifier); 124 | }]; 125 | return request; 126 | } 127 | 128 | #pragma mark - delegate 129 | 130 | - (void)requestDidFinish:(THttpRequest *)request 131 | { 132 | NSLog(@"%@ data:%@",request.responseObject,request.responseObject.data); 133 | [MBProgressHUD showSuccess:@"加载成功!" toView:self.view]; 134 | } 135 | 136 | - (void)requestDidFail:(THttpRequest *)request error:(NSError *)error 137 | { 138 | [MBProgressHUD showError:@"加载失败!" toView:self.view]; 139 | } 140 | 141 | - (void)didReceiveMemoryWarning { 142 | [super didReceiveMemoryWarning]; 143 | // Dispose of any resources that can be recreated. 144 | } 145 | 146 | @end 147 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/AFNetworking/AFSecurityPolicy.h: -------------------------------------------------------------------------------- 1 | // AFSecurityPolicy.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | #import 24 | 25 | typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { 26 | AFSSLPinningModeNone, 27 | AFSSLPinningModePublicKey, 28 | AFSSLPinningModeCertificate, 29 | }; 30 | 31 | /** 32 | `AFSecurityPolicy` evaluates server trust against pinned X.509 certificates and public keys over secure connections. 33 | 34 | Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled. 35 | */ 36 | 37 | NS_ASSUME_NONNULL_BEGIN 38 | 39 | @interface AFSecurityPolicy : NSObject 40 | 41 | /** 42 | The criteria by which server trust should be evaluated against the pinned SSL certificates. Defaults to `AFSSLPinningModeNone`. 43 | */ 44 | @property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode; 45 | 46 | /** 47 | The certificates used to evaluate server trust according to the SSL pinning mode. 48 | 49 | By default, this property is set to any (`.cer`) certificates included in the target compiling AFNetworking. Note that if you are using AFNetworking as embedded framework, no certificates will be pinned by default. Use `certificatesInBundle` to load certificates from your target, and then create a new policy by calling `policyWithPinningMode:withPinnedCertificates`. 50 | 51 | Note that if pinning is enabled, `evaluateServerTrust:forDomain:` will return true if any pinned certificate matches. 52 | */ 53 | @property (nonatomic, strong, nullable) NSSet *pinnedCertificates; 54 | 55 | /** 56 | Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`. 57 | */ 58 | @property (nonatomic, assign) BOOL allowInvalidCertificates; 59 | 60 | /** 61 | Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES`. 62 | */ 63 | @property (nonatomic, assign) BOOL validatesDomainName; 64 | 65 | ///----------------------------------------- 66 | /// @name Getting Certificates from the Bundle 67 | ///----------------------------------------- 68 | 69 | /** 70 | Returns any certificates included in the bundle. If you are using AFNetworking as an embedded framework, you must use this method to find the certificates you have included in your app bundle, and use them when creating your security policy by calling `policyWithPinningMode:withPinnedCertificates`. 71 | 72 | @return The certificates included in the given bundle. 73 | */ 74 | + (NSSet *)certificatesInBundle:(NSBundle *)bundle; 75 | 76 | ///----------------------------------------- 77 | /// @name Getting Specific Security Policies 78 | ///----------------------------------------- 79 | 80 | /** 81 | Returns the shared default security policy, which does not allow invalid certificates, validates domain name, and does not validate against pinned certificates or public keys. 82 | 83 | @return The default security policy. 84 | */ 85 | + (instancetype)defaultPolicy; 86 | 87 | ///--------------------- 88 | /// @name Initialization 89 | ///--------------------- 90 | 91 | /** 92 | Creates and returns a security policy with the specified pinning mode. 93 | 94 | @param pinningMode The SSL pinning mode. 95 | 96 | @return A new security policy. 97 | */ 98 | + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode; 99 | 100 | /** 101 | Creates and returns a security policy with the specified pinning mode. 102 | 103 | @param pinningMode The SSL pinning mode. 104 | @param pinnedCertificates The certificates to pin against. 105 | 106 | @return A new security policy. 107 | */ 108 | + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode withPinnedCertificates:(NSSet *)pinnedCertificates; 109 | 110 | ///------------------------------ 111 | /// @name Evaluating Server Trust 112 | ///------------------------------ 113 | 114 | /** 115 | Whether or not the specified server trust should be accepted, based on the security policy. 116 | 117 | This method should be used when responding to an authentication challenge from a server. 118 | 119 | @param serverTrust The X.509 certificate trust of the server. 120 | @param domain The domain of serverTrust. If `nil`, the domain will not be validated. 121 | 122 | @return Whether or not to trust the server. 123 | */ 124 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust 125 | forDomain:(nullable NSString *)domain; 126 | 127 | @end 128 | 129 | NS_ASSUME_NONNULL_END 130 | 131 | ///---------------- 132 | /// @name Constants 133 | ///---------------- 134 | 135 | /** 136 | ## SSL Pinning Modes 137 | 138 | The following constants are provided by `AFSSLPinningMode` as possible SSL pinning modes. 139 | 140 | enum { 141 | AFSSLPinningModeNone, 142 | AFSSLPinningModePublicKey, 143 | AFSSLPinningModeCertificate, 144 | } 145 | 146 | `AFSSLPinningModeNone` 147 | Do not used pinned certificates to validate servers. 148 | 149 | `AFSSLPinningModePublicKey` 150 | Validate host certificates against public keys of pinned certificates. 151 | 152 | `AFSSLPinningModeCertificate` 153 | Validate host certificates against pinned certificates. 154 | */ 155 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 27 | 34 | 41 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYResponseCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // TYResponseCache.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/24. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYResponseCache.h" 10 | #import 11 | 12 | @interface TYResponseCache () 13 | 14 | @property (nonatomic, strong) NSFileManager *fileManager; 15 | @property (nonatomic, strong) NSString *cachePath; 16 | @property (nonatomic, strong) dispatch_queue_t queue; 17 | 18 | @end 19 | 20 | static NSString * const TYRequestManagerCacheDirectory = @"TYRequestCacheDirectory"; 21 | 22 | @implementation TYResponseCache 23 | 24 | + (dispatch_queue_t)cacheQueue { 25 | static dispatch_queue_t cacheQueue = NULL; 26 | static dispatch_once_t onceToken; 27 | dispatch_once(&onceToken, ^{ 28 | cacheQueue = dispatch_queue_create("com.TYResponseCache.cacheQueue", DISPATCH_QUEUE_CONCURRENT); 29 | dispatch_set_target_queue(cacheQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); 30 | }); 31 | return cacheQueue; 32 | } 33 | 34 | - (dispatch_queue_t)queue 35 | { 36 | return [[self class] cacheQueue]; 37 | } 38 | 39 | - (NSString *)cachePath 40 | { 41 | if (_cachePath == nil) { 42 | _cachePath = [self createCachesDirectory]; 43 | } 44 | return _cachePath; 45 | } 46 | 47 | - (NSFileManager *)fileManager 48 | { 49 | @synchronized (_fileManager) { 50 | if (_fileManager == nil) { 51 | _fileManager = [NSFileManager defaultManager]; 52 | } 53 | return _fileManager; 54 | } 55 | } 56 | 57 | - (NSString *)createCachesDirectory 58 | { 59 | NSString *cachePathDic = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 60 | NSString *cachePath = [cachePathDic stringByAppendingPathComponent:TYRequestManagerCacheDirectory]; 61 | BOOL isDirectory; 62 | if (![self.fileManager fileExistsAtPath:cachePath isDirectory:&isDirectory]) { 63 | __autoreleasing NSError *error = nil; 64 | BOOL created = [self.fileManager createDirectoryAtPath:cachePath withIntermediateDirectories:YES attributes:nil error:&error]; 65 | if (!created) { 66 | NSLog(@"<> - create cache directory failed with error:%@", error); 67 | } 68 | } 69 | return cachePath; 70 | } 71 | 72 | - (NSString *)md5String:(NSString *)str 73 | { 74 | const char *cStr = [str UTF8String]; 75 | if (cStr == NULL) { 76 | cStr = ""; 77 | } 78 | unsigned char result[CC_MD5_DIGEST_LENGTH]; 79 | CC_MD5( cStr, (CC_LONG)strlen(cStr), result ); 80 | return [NSString stringWithFormat: 81 | @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", 82 | result[0], result[1], result[2], result[3], 83 | result[4], result[5], result[6], result[7], 84 | result[8], result[9], result[10], result[11], 85 | result[12], result[13], result[14], result[15] 86 | ]; 87 | } 88 | 89 | - (void)setObject:(id)object forKey:(NSString *)key 90 | { 91 | NSString *encodedKey = [self md5String:key]; 92 | NSString *cachePath = self.cachePath; 93 | dispatch_async([self queue], ^{ 94 | NSString *filePath = [cachePath stringByAppendingPathComponent:encodedKey]; 95 | BOOL written = [NSKeyedArchiver archiveRootObject:object toFile:filePath]; 96 | if (!written) { 97 | NSLog(@"<> - set object to file failed"); 98 | } 99 | }); 100 | } 101 | 102 | - (id )objectForKey:(NSString *)key 103 | { 104 | return [self objectForKey:key overdueDate:nil]; 105 | } 106 | 107 | - (id)objectForKey:(NSString *)key overdueDate:(NSDate *)overdueDate 108 | { 109 | NSString *encodedKey = [self md5String:key]; 110 | id object = nil; 111 | NSString *filePath = [self.cachePath stringByAppendingPathComponent:encodedKey]; 112 | 113 | if ([self.fileManager fileExistsAtPath:filePath] ) { 114 | NSDate *modificationDate = [self cacheDateFilePath:filePath]; 115 | if (!overdueDate || modificationDate.timeIntervalSince1970 - overdueDate.timeIntervalSince1970 >= 0) { 116 | object = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; 117 | }else { 118 | NSLog(@"file cache was overdue"); 119 | } 120 | } 121 | return object; 122 | } 123 | 124 | - (void)removeObjectForKey:(NSString *)key 125 | { 126 | NSString *encodedKey = [self md5String:key]; 127 | NSString *filePath = [self.cachePath stringByAppendingPathComponent:encodedKey]; 128 | if ([self.fileManager fileExistsAtPath:filePath]) { 129 | __autoreleasing NSError *error = nil; 130 | BOOL removed = [self.fileManager removeItemAtPath:filePath error:&error]; 131 | if (!removed) { 132 | NSLog(@"<> - remove item failed with error:%@", error); 133 | } 134 | } 135 | } 136 | 137 | - (void)removeAllObjects 138 | { 139 | __autoreleasing NSError *error; 140 | BOOL removed = [self.fileManager removeItemAtPath:self.cachePath error:&error]; 141 | if (!removed) { 142 | NSLog(@" - remove cache directory failed with error:%@", error); 143 | } 144 | } 145 | 146 | #pragma mark - private 147 | 148 | - (NSDate *)cacheDateFilePath:(NSString *)path { 149 | // get file attribute 150 | NSError *attributesRetrievalError = nil; 151 | NSDictionary *attributes = [self.fileManager attributesOfItemAtPath:path 152 | error:&attributesRetrievalError]; 153 | if (!attributes) { 154 | NSLog(@"Error get attributes for file at %@: %@", path, attributesRetrievalError); 155 | return nil; 156 | } 157 | return [attributes fileModificationDate]; 158 | } 159 | 160 | - (void)trimToDate:(NSDate *)date 161 | { 162 | __autoreleasing NSError *error = nil; 163 | NSArray *files = [self.fileManager contentsOfDirectoryAtURL:[NSURL URLWithString:self.cachePath] 164 | includingPropertiesForKeys:@[NSURLContentModificationDateKey] 165 | options:NSDirectoryEnumerationSkipsHiddenFiles 166 | error:&error]; 167 | if (error) { 168 | NSLog(@" - get files error:%@", error); 169 | } 170 | 171 | dispatch_async([self queue], ^{ 172 | for (NSURL *fileURL in files) { 173 | NSDictionary *dictionary = [fileURL resourceValuesForKeys:@[NSURLContentModificationDateKey] error:nil]; 174 | NSDate *modificationDate = [dictionary objectForKey:NSURLContentModificationDateKey]; 175 | if (modificationDate.timeIntervalSince1970 - date.timeIntervalSince1970 < 0) { 176 | NSError *error = nil; 177 | if ([self.fileManager removeItemAtURL:fileURL error:&error]) { 178 | NSLog(@"delete cache yes"); 179 | } else { 180 | NSLog(@"delete cache no %@",fileURL.absoluteString); 181 | 182 | } 183 | 184 | } 185 | } 186 | }); 187 | } 188 | 189 | @end 190 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYHttpManager/TYHttpManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // TYHttpManager.m 3 | // TYHttpManagerDemo 4 | // 5 | // Created by tany on 16/5/23. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "TYHttpManager.h" 10 | #import "AFNetworking.h" 11 | 12 | @implementation TYHttpManager 13 | 14 | #pragma mark - init 15 | 16 | + (TYHttpManager *)sharedInstance { 17 | static id sharedInstance = nil; 18 | static dispatch_once_t onceToken; 19 | dispatch_once(&onceToken, ^{ 20 | sharedInstance = [[self alloc] init]; 21 | }); 22 | return sharedInstance; 23 | } 24 | 25 | + (dispatch_queue_t)completeQueue { 26 | static dispatch_queue_t completeQueue = NULL; 27 | static dispatch_once_t onceToken; 28 | dispatch_once(&onceToken, ^{ 29 | completeQueue = dispatch_queue_create("com.TYHttpManager.completeQueue", DISPATCH_QUEUE_SERIAL); 30 | dispatch_set_target_queue(completeQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); 31 | }); 32 | return completeQueue; 33 | } 34 | 35 | - (instancetype)init 36 | { 37 | if (self = [super init]) { 38 | _requestConfiguration = [TYRequstConfigure sharedInstance]; 39 | } 40 | return self; 41 | } 42 | 43 | #pragma maek - add request 44 | 45 | - (void)addRequest:(id)request 46 | { 47 | AFHTTPSessionManager *manager = [self defaultSessionManagerWithRequest:request]; 48 | 49 | [self configureSessionManager:manager request:request]; 50 | 51 | [self loadRequest:request sessionManager:manager]; 52 | } 53 | 54 | - (void)cancleRequest:(id)request 55 | { 56 | [request cancle]; 57 | } 58 | 59 | #pragma mark - configure http manager 60 | 61 | - (AFHTTPSessionManager *)defaultSessionManagerWithRequest:(id)request 62 | { 63 | TYRequstConfigure *requestConfiguration = [request configuration]; 64 | if (requestConfiguration == nil) { 65 | requestConfiguration = self.requestConfiguration; 66 | } 67 | 68 | AFHTTPSessionManager *manager = nil; 69 | if (requestConfiguration.sessionConfiguration) { 70 | manager = [[AFHTTPSessionManager alloc]initWithBaseURL:[NSURL URLWithString:requestConfiguration.baseURL] sessionConfiguration:requestConfiguration.sessionConfiguration]; 71 | }else { 72 | manager = [AFHTTPSessionManager manager]; 73 | } 74 | manager.completionQueue = [[self class] completeQueue]; 75 | return manager; 76 | } 77 | 78 | - (void)configureSessionManager:(AFHTTPSessionManager *)manager request:(id)request 79 | { 80 | if ([request serializerType] == TYRequestSerializerTypeJSON) { 81 | manager.requestSerializer = [AFJSONRequestSerializer serializer]; 82 | }else if ([request serializerType] == TYRequestSerializerTypeString) { 83 | manager.requestSerializer = [AFJSONRequestSerializer serializer]; 84 | manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments]; 85 | } 86 | 87 | NSDictionary *headerFieldValue = [request headerFieldValues]; 88 | if (headerFieldValue) { 89 | [headerFieldValue enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL * stop) { 90 | if ([key isKindOfClass:[NSString class]] && [value isKindOfClass:[NSString class]]) { 91 | [manager.requestSerializer setValue:value forHTTPHeaderField:key]; 92 | } 93 | }]; 94 | } 95 | 96 | manager.requestSerializer.cachePolicy = [request cachePolicy]; 97 | manager.requestSerializer.timeoutInterval = [request timeoutInterval]; 98 | manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/plain", @"text/javascript", @"text/json", @"text/html", nil]; 99 | } 100 | 101 | - (NSString *)buildRequstURL:(id)request 102 | { 103 | NSString *URLPath = [request URLString]; 104 | if ([URLPath hasPrefix:@"http:"] ) { 105 | return URLPath; 106 | } 107 | 108 | NSString *baseURL = request.baseURL.length > 0 ? request.baseURL : (request.configuration ? request.configuration.baseURL : [TYRequstConfigure sharedInstance].baseURL); 109 | 110 | return [NSString stringWithFormat:@"%@%@",baseURL?baseURL:@"",URLPath]; 111 | } 112 | 113 | - (void)loadRequest:(id)request sessionManager:(AFHTTPSessionManager *)manager 114 | { 115 | NSString *URLString = [self buildRequstURL:request]; 116 | NSDictionary *parameters = [request parameters]; 117 | 118 | TYRequestMethod requestMethod = [request method]; 119 | AFProgressBlock progressBlock = [request progressBlock]; 120 | 121 | if (requestMethod == TYRequestMethodGet) { 122 | 123 | request.dataTask = [manager GET:URLString parameters:parameters progress:progressBlock success:^(NSURLSessionDataTask * task, id responseObject) { 124 | [request requestDidResponse:responseObject error:nil]; 125 | } failure:^(NSURLSessionDataTask * task, NSError * error) { 126 | [request requestDidResponse:nil error:error]; 127 | }]; 128 | }else if (requestMethod == TYRequestMethodPost) { 129 | 130 | AFConstructingBodyBlock constructingBodyBlock = [request constructingBodyBlock]; 131 | if (constructingBodyBlock) { 132 | request.dataTask = [manager POST:URLString parameters:parameters constructingBodyWithBlock:constructingBodyBlock progress:progressBlock success:^(NSURLSessionDataTask * task, id responseObject) { 133 | [request requestDidResponse:responseObject error:nil]; 134 | } failure:^(NSURLSessionDataTask * task, NSError * error) { 135 | [request requestDidResponse:nil error:error]; 136 | }]; 137 | }else { 138 | request.dataTask = [manager POST:URLString parameters:parameters progress:progressBlock success:^(NSURLSessionDataTask * task, id responseObject) { 139 | [request requestDidResponse:responseObject error:nil]; 140 | } failure:^(NSURLSessionDataTask * task, NSError * error) { 141 | [request requestDidResponse:nil error:error]; 142 | }]; 143 | } 144 | }else if (requestMethod == TYRequestMethodHead) { 145 | 146 | request.dataTask = [manager HEAD:URLString parameters:parameters success:^(NSURLSessionDataTask * task) { 147 | [request requestDidResponse:nil error:nil]; 148 | } failure:^(NSURLSessionDataTask * task, NSError * error) { 149 | [request requestDidResponse:nil error:error]; 150 | }]; 151 | }else if (requestMethod == TYRequestMethodPut) { 152 | 153 | request.dataTask = [manager PUT:URLString parameters:parameters success:^(NSURLSessionDataTask * task, id responseObject) { 154 | [request requestDidResponse:responseObject error:nil]; 155 | } failure:^(NSURLSessionDataTask * task, NSError * error) { 156 | [request requestDidResponse:nil error:error]; 157 | }]; 158 | }else if (requestMethod == TYRequestMethodPatch) { 159 | 160 | request.dataTask = [manager PATCH:URLString parameters:parameters success:^(NSURLSessionDataTask * task, id responseObject) { 161 | [request requestDidResponse:responseObject error:nil]; 162 | } failure:^(NSURLSessionDataTask * task, NSError * error) { 163 | [request requestDidResponse:nil error:error]; 164 | }]; 165 | } 166 | } 167 | 168 | @end 169 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/AFNetworking/AFNetworkReachabilityManager.h: -------------------------------------------------------------------------------- 1 | // AFNetworkReachabilityManager.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | 24 | #if !TARGET_OS_WATCH 25 | #import 26 | 27 | typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { 28 | AFNetworkReachabilityStatusUnknown = -1, 29 | AFNetworkReachabilityStatusNotReachable = 0, 30 | AFNetworkReachabilityStatusReachableViaWWAN = 1, 31 | AFNetworkReachabilityStatusReachableViaWiFi = 2, 32 | }; 33 | 34 | NS_ASSUME_NONNULL_BEGIN 35 | 36 | /** 37 | `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. 38 | 39 | Reachability can be used to determine background information about why a network operation failed, or to trigger a network operation retrying when a connection is established. It should not be used to prevent a user from initiating a network request, as it's possible that an initial request may be required to establish reachability. 40 | 41 | See Apple's Reachability Sample Code ( https://developer.apple.com/library/ios/samplecode/reachability/ ) 42 | 43 | @warning Instances of `AFNetworkReachabilityManager` must be started with `-startMonitoring` before reachability status can be determined. 44 | */ 45 | @interface AFNetworkReachabilityManager : NSObject 46 | 47 | /** 48 | The current network reachability status. 49 | */ 50 | @property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; 51 | 52 | /** 53 | Whether or not the network is currently reachable. 54 | */ 55 | @property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable; 56 | 57 | /** 58 | Whether or not the network is currently reachable via WWAN. 59 | */ 60 | @property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN; 61 | 62 | /** 63 | Whether or not the network is currently reachable via WiFi. 64 | */ 65 | @property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi; 66 | 67 | ///--------------------- 68 | /// @name Initialization 69 | ///--------------------- 70 | 71 | /** 72 | Returns the shared network reachability manager. 73 | */ 74 | + (instancetype)sharedManager; 75 | 76 | /** 77 | Creates and returns a network reachability manager with the default socket address. 78 | 79 | @return An initialized network reachability manager, actively monitoring the default socket address. 80 | */ 81 | + (instancetype)manager; 82 | 83 | /** 84 | Creates and returns a network reachability manager for the specified domain. 85 | 86 | @param domain The domain used to evaluate network reachability. 87 | 88 | @return An initialized network reachability manager, actively monitoring the specified domain. 89 | */ 90 | + (instancetype)managerForDomain:(NSString *)domain; 91 | 92 | /** 93 | Creates and returns a network reachability manager for the socket address. 94 | 95 | @param address The socket address (`sockaddr_in6`) used to evaluate network reachability. 96 | 97 | @return An initialized network reachability manager, actively monitoring the specified socket address. 98 | */ 99 | + (instancetype)managerForAddress:(const void *)address; 100 | 101 | /** 102 | Initializes an instance of a network reachability manager from the specified reachability object. 103 | 104 | @param reachability The reachability object to monitor. 105 | 106 | @return An initialized network reachability manager, actively monitoring the specified reachability. 107 | */ 108 | - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER; 109 | 110 | ///-------------------------------------------------- 111 | /// @name Starting & Stopping Reachability Monitoring 112 | ///-------------------------------------------------- 113 | 114 | /** 115 | Starts monitoring for changes in network reachability status. 116 | */ 117 | - (void)startMonitoring; 118 | 119 | /** 120 | Stops monitoring for changes in network reachability status. 121 | */ 122 | - (void)stopMonitoring; 123 | 124 | ///------------------------------------------------- 125 | /// @name Getting Localized Reachability Description 126 | ///------------------------------------------------- 127 | 128 | /** 129 | Returns a localized string representation of the current network reachability status. 130 | */ 131 | - (NSString *)localizedNetworkReachabilityStatusString; 132 | 133 | ///--------------------------------------------------- 134 | /// @name Setting Network Reachability Change Callback 135 | ///--------------------------------------------------- 136 | 137 | /** 138 | Sets a callback to be executed when the network availability of the `baseURL` host changes. 139 | 140 | @param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`. 141 | */ 142 | - (void)setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block; 143 | 144 | @end 145 | 146 | ///---------------- 147 | /// @name Constants 148 | ///---------------- 149 | 150 | /** 151 | ## Network Reachability 152 | 153 | The following constants are provided by `AFNetworkReachabilityManager` as possible network reachability statuses. 154 | 155 | enum { 156 | AFNetworkReachabilityStatusUnknown, 157 | AFNetworkReachabilityStatusNotReachable, 158 | AFNetworkReachabilityStatusReachableViaWWAN, 159 | AFNetworkReachabilityStatusReachableViaWiFi, 160 | } 161 | 162 | `AFNetworkReachabilityStatusUnknown` 163 | The `baseURL` host reachability is not known. 164 | 165 | `AFNetworkReachabilityStatusNotReachable` 166 | The `baseURL` host cannot be reached. 167 | 168 | `AFNetworkReachabilityStatusReachableViaWWAN` 169 | The `baseURL` host can be reached via a cellular connection, such as EDGE or GPRS. 170 | 171 | `AFNetworkReachabilityStatusReachableViaWiFi` 172 | The `baseURL` host can be reached via a Wi-Fi connection. 173 | 174 | ### Keys for Notification UserInfo Dictionary 175 | 176 | Strings that are used as keys in a `userInfo` dictionary in a network reachability status change notification. 177 | 178 | `AFNetworkingReachabilityNotificationStatusItem` 179 | A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification. 180 | The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status. 181 | */ 182 | 183 | ///-------------------- 184 | /// @name Notifications 185 | ///-------------------- 186 | 187 | /** 188 | Posted when network reachability changes. 189 | This notification assigns no notification object. The `userInfo` dictionary contains an `NSNumber` object under the `AFNetworkingReachabilityNotificationStatusItem` key, representing the `AFNetworkReachabilityStatus` value for the current network reachability. 190 | 191 | @warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import ` to the header prefix of the project (`Prefix.pch`). 192 | */ 193 | FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityDidChangeNotification; 194 | FOUNDATION_EXPORT NSString * const AFNetworkingReachabilityNotificationStatusItem; 195 | 196 | ///-------------------- 197 | /// @name Functions 198 | ///-------------------- 199 | 200 | /** 201 | Returns a localized string representation of an `AFNetworkReachabilityStatus` value. 202 | */ 203 | FOUNDATION_EXPORT NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); 204 | 205 | NS_ASSUME_NONNULL_END 206 | #endif 207 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/AFNetworking/AFNetworkReachabilityManager.m: -------------------------------------------------------------------------------- 1 | // AFNetworkReachabilityManager.m 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "AFNetworkReachabilityManager.h" 23 | #if !TARGET_OS_WATCH 24 | 25 | #import 26 | #import 27 | #import 28 | #import 29 | #import 30 | 31 | NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change"; 32 | NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem"; 33 | 34 | typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status); 35 | 36 | NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status) { 37 | switch (status) { 38 | case AFNetworkReachabilityStatusNotReachable: 39 | return NSLocalizedStringFromTable(@"Not Reachable", @"AFNetworking", nil); 40 | case AFNetworkReachabilityStatusReachableViaWWAN: 41 | return NSLocalizedStringFromTable(@"Reachable via WWAN", @"AFNetworking", nil); 42 | case AFNetworkReachabilityStatusReachableViaWiFi: 43 | return NSLocalizedStringFromTable(@"Reachable via WiFi", @"AFNetworking", nil); 44 | case AFNetworkReachabilityStatusUnknown: 45 | default: 46 | return NSLocalizedStringFromTable(@"Unknown", @"AFNetworking", nil); 47 | } 48 | } 49 | 50 | static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) { 51 | BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0); 52 | BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0); 53 | BOOL canConnectionAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)); 54 | BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0); 55 | BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction)); 56 | 57 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown; 58 | if (isNetworkReachable == NO) { 59 | status = AFNetworkReachabilityStatusNotReachable; 60 | } 61 | #if TARGET_OS_IPHONE 62 | else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) { 63 | status = AFNetworkReachabilityStatusReachableViaWWAN; 64 | } 65 | #endif 66 | else { 67 | status = AFNetworkReachabilityStatusReachableViaWiFi; 68 | } 69 | 70 | return status; 71 | } 72 | 73 | /** 74 | * Queue a status change notification for the main thread. 75 | * 76 | * This is done to ensure that the notifications are received in the same order 77 | * as they are sent. If notifications are sent directly, it is possible that 78 | * a queued notification (for an earlier status condition) is processed after 79 | * the later update, resulting in the listener being left in the wrong state. 80 | */ 81 | static void AFPostReachabilityStatusChange(SCNetworkReachabilityFlags flags, AFNetworkReachabilityStatusBlock block) { 82 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); 83 | dispatch_async(dispatch_get_main_queue(), ^{ 84 | if (block) { 85 | block(status); 86 | } 87 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 88 | NSDictionary *userInfo = @{ AFNetworkingReachabilityNotificationStatusItem: @(status) }; 89 | [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:userInfo]; 90 | }); 91 | } 92 | 93 | static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) { 94 | AFPostReachabilityStatusChange(flags, (__bridge AFNetworkReachabilityStatusBlock)info); 95 | } 96 | 97 | 98 | static const void * AFNetworkReachabilityRetainCallback(const void *info) { 99 | return Block_copy(info); 100 | } 101 | 102 | static void AFNetworkReachabilityReleaseCallback(const void *info) { 103 | if (info) { 104 | Block_release(info); 105 | } 106 | } 107 | 108 | @interface AFNetworkReachabilityManager () 109 | @property (readonly, nonatomic, assign) SCNetworkReachabilityRef networkReachability; 110 | @property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; 111 | @property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock; 112 | @end 113 | 114 | @implementation AFNetworkReachabilityManager 115 | 116 | + (instancetype)sharedManager { 117 | static AFNetworkReachabilityManager *_sharedManager = nil; 118 | static dispatch_once_t onceToken; 119 | dispatch_once(&onceToken, ^{ 120 | _sharedManager = [self manager]; 121 | }); 122 | 123 | return _sharedManager; 124 | } 125 | 126 | + (instancetype)managerForDomain:(NSString *)domain { 127 | SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]); 128 | 129 | AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; 130 | 131 | CFRelease(reachability); 132 | 133 | return manager; 134 | } 135 | 136 | + (instancetype)managerForAddress:(const void *)address { 137 | SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address); 138 | AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; 139 | 140 | CFRelease(reachability); 141 | 142 | return manager; 143 | } 144 | 145 | + (instancetype)manager 146 | { 147 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 90000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) 148 | struct sockaddr_in6 address; 149 | bzero(&address, sizeof(address)); 150 | address.sin6_len = sizeof(address); 151 | address.sin6_family = AF_INET6; 152 | #else 153 | struct sockaddr_in address; 154 | bzero(&address, sizeof(address)); 155 | address.sin_len = sizeof(address); 156 | address.sin_family = AF_INET; 157 | #endif 158 | return [self managerForAddress:&address]; 159 | } 160 | 161 | - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { 162 | self = [super init]; 163 | if (!self) { 164 | return nil; 165 | } 166 | 167 | _networkReachability = CFRetain(reachability); 168 | self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown; 169 | 170 | return self; 171 | } 172 | 173 | - (instancetype)init NS_UNAVAILABLE 174 | { 175 | return nil; 176 | } 177 | 178 | - (void)dealloc { 179 | [self stopMonitoring]; 180 | 181 | if (_networkReachability != NULL) { 182 | CFRelease(_networkReachability); 183 | } 184 | } 185 | 186 | #pragma mark - 187 | 188 | - (BOOL)isReachable { 189 | return [self isReachableViaWWAN] || [self isReachableViaWiFi]; 190 | } 191 | 192 | - (BOOL)isReachableViaWWAN { 193 | return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWWAN; 194 | } 195 | 196 | - (BOOL)isReachableViaWiFi { 197 | return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWiFi; 198 | } 199 | 200 | #pragma mark - 201 | 202 | - (void)startMonitoring { 203 | [self stopMonitoring]; 204 | 205 | if (!self.networkReachability) { 206 | return; 207 | } 208 | 209 | __weak __typeof(self)weakSelf = self; 210 | AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) { 211 | __strong __typeof(weakSelf)strongSelf = weakSelf; 212 | 213 | strongSelf.networkReachabilityStatus = status; 214 | if (strongSelf.networkReachabilityStatusBlock) { 215 | strongSelf.networkReachabilityStatusBlock(status); 216 | } 217 | 218 | }; 219 | 220 | SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL}; 221 | SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context); 222 | SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); 223 | 224 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{ 225 | SCNetworkReachabilityFlags flags; 226 | if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) { 227 | AFPostReachabilityStatusChange(flags, callback); 228 | } 229 | }); 230 | } 231 | 232 | - (void)stopMonitoring { 233 | if (!self.networkReachability) { 234 | return; 235 | } 236 | 237 | SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); 238 | } 239 | 240 | #pragma mark - 241 | 242 | - (NSString *)localizedNetworkReachabilityStatusString { 243 | return AFStringFromNetworkReachabilityStatus(self.networkReachabilityStatus); 244 | } 245 | 246 | #pragma mark - 247 | 248 | - (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block { 249 | self.networkReachabilityStatusBlock = block; 250 | } 251 | 252 | #pragma mark - NSKeyValueObserving 253 | 254 | + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { 255 | if ([key isEqualToString:@"reachable"] || [key isEqualToString:@"reachableViaWWAN"] || [key isEqualToString:@"reachableViaWiFi"]) { 256 | return [NSSet setWithObject:@"networkReachabilityStatus"]; 257 | } 258 | 259 | return [super keyPathsForValuesAffectingValueForKey:key]; 260 | } 261 | 262 | @end 263 | #endif 264 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/AFNetworking/AFURLResponseSerialization.h: -------------------------------------------------------------------------------- 1 | // AFURLResponseSerialization.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | #import 24 | 25 | NS_ASSUME_NONNULL_BEGIN 26 | 27 | /** 28 | The `AFURLResponseSerialization` protocol is adopted by an object that decodes data into a more useful object representation, according to details in the server response. Response serializers may additionally perform validation on the incoming response and data. 29 | 30 | For example, a JSON response serializer may check for an acceptable status code (`2XX` range) and content type (`application/json`), decoding a valid JSON response into an object. 31 | */ 32 | @protocol AFURLResponseSerialization 33 | 34 | /** 35 | The response object decoded from the data associated with a specified response. 36 | 37 | @param response The response to be processed. 38 | @param data The response data to be decoded. 39 | @param error The error that occurred while attempting to decode the response data. 40 | 41 | @return The object decoded from the specified response data. 42 | */ 43 | - (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response 44 | data:(nullable NSData *)data 45 | error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW; 46 | 47 | @end 48 | 49 | #pragma mark - 50 | 51 | /** 52 | `AFHTTPResponseSerializer` conforms to the `AFURLRequestSerialization` & `AFURLResponseSerialization` protocols, offering a concrete base implementation of query string / URL form-encoded parameter serialization and default request headers, as well as response status code and content type validation. 53 | 54 | Any request or response serializer dealing with HTTP is encouraged to subclass `AFHTTPResponseSerializer` in order to ensure consistent default behavior. 55 | */ 56 | @interface AFHTTPResponseSerializer : NSObject 57 | 58 | - (instancetype)init; 59 | 60 | /** 61 | The string encoding used to serialize data received from the server, when no string encoding is specified by the response. `NSUTF8StringEncoding` by default. 62 | */ 63 | @property (nonatomic, assign) NSStringEncoding stringEncoding; 64 | 65 | /** 66 | Creates and returns a serializer with default configuration. 67 | */ 68 | + (instancetype)serializer; 69 | 70 | ///----------------------------------------- 71 | /// @name Configuring Response Serialization 72 | ///----------------------------------------- 73 | 74 | /** 75 | The acceptable HTTP status codes for responses. When non-`nil`, responses with status codes not contained by the set will result in an error during validation. 76 | 77 | See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 78 | */ 79 | @property (nonatomic, copy, nullable) NSIndexSet *acceptableStatusCodes; 80 | 81 | /** 82 | The acceptable MIME types for responses. When non-`nil`, responses with a `Content-Type` with MIME types that do not intersect with the set will result in an error during validation. 83 | */ 84 | @property (nonatomic, copy, nullable) NSSet *acceptableContentTypes; 85 | 86 | /** 87 | Validates the specified response and data. 88 | 89 | In its base implementation, this method checks for an acceptable status code and content type. Subclasses may wish to add other domain-specific checks. 90 | 91 | @param response The response to be validated. 92 | @param data The data associated with the response. 93 | @param error The error that occurred while attempting to validate the response. 94 | 95 | @return `YES` if the response is valid, otherwise `NO`. 96 | */ 97 | - (BOOL)validateResponse:(nullable NSHTTPURLResponse *)response 98 | data:(nullable NSData *)data 99 | error:(NSError * _Nullable __autoreleasing *)error; 100 | 101 | @end 102 | 103 | #pragma mark - 104 | 105 | 106 | /** 107 | `AFJSONResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes JSON responses. 108 | 109 | By default, `AFJSONResponseSerializer` accepts the following MIME types, which includes the official standard, `application/json`, as well as other commonly-used types: 110 | 111 | - `application/json` 112 | - `text/json` 113 | - `text/javascript` 114 | */ 115 | @interface AFJSONResponseSerializer : AFHTTPResponseSerializer 116 | 117 | - (instancetype)init; 118 | 119 | /** 120 | Options for reading the response JSON data and creating the Foundation objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. 121 | */ 122 | @property (nonatomic, assign) NSJSONReadingOptions readingOptions; 123 | 124 | /** 125 | Whether to remove keys with `NSNull` values from response JSON. Defaults to `NO`. 126 | */ 127 | @property (nonatomic, assign) BOOL removesKeysWithNullValues; 128 | 129 | /** 130 | Creates and returns a JSON serializer with specified reading and writing options. 131 | 132 | @param readingOptions The specified JSON reading options. 133 | */ 134 | + (instancetype)serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions; 135 | 136 | @end 137 | 138 | #pragma mark - 139 | 140 | /** 141 | `AFXMLParserResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLParser` objects. 142 | 143 | By default, `AFXMLParserResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types: 144 | 145 | - `application/xml` 146 | - `text/xml` 147 | */ 148 | @interface AFXMLParserResponseSerializer : AFHTTPResponseSerializer 149 | 150 | @end 151 | 152 | #pragma mark - 153 | 154 | #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED 155 | 156 | /** 157 | `AFXMLDocumentResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects. 158 | 159 | By default, `AFXMLDocumentResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types: 160 | 161 | - `application/xml` 162 | - `text/xml` 163 | */ 164 | @interface AFXMLDocumentResponseSerializer : AFHTTPResponseSerializer 165 | 166 | - (instancetype)init; 167 | 168 | /** 169 | Input and output options specifically intended for `NSXMLDocument` objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. 170 | */ 171 | @property (nonatomic, assign) NSUInteger options; 172 | 173 | /** 174 | Creates and returns an XML document serializer with the specified options. 175 | 176 | @param mask The XML document options. 177 | */ 178 | + (instancetype)serializerWithXMLDocumentOptions:(NSUInteger)mask; 179 | 180 | @end 181 | 182 | #endif 183 | 184 | #pragma mark - 185 | 186 | /** 187 | `AFPropertyListResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects. 188 | 189 | By default, `AFPropertyListResponseSerializer` accepts the following MIME types: 190 | 191 | - `application/x-plist` 192 | */ 193 | @interface AFPropertyListResponseSerializer : AFHTTPResponseSerializer 194 | 195 | - (instancetype)init; 196 | 197 | /** 198 | The property list format. Possible values are described in "NSPropertyListFormat". 199 | */ 200 | @property (nonatomic, assign) NSPropertyListFormat format; 201 | 202 | /** 203 | The property list reading options. Possible values are described in "NSPropertyListMutabilityOptions." 204 | */ 205 | @property (nonatomic, assign) NSPropertyListReadOptions readOptions; 206 | 207 | /** 208 | Creates and returns a property list serializer with a specified format, read options, and write options. 209 | 210 | @param format The property list format. 211 | @param readOptions The property list reading options. 212 | */ 213 | + (instancetype)serializerWithFormat:(NSPropertyListFormat)format 214 | readOptions:(NSPropertyListReadOptions)readOptions; 215 | 216 | @end 217 | 218 | #pragma mark - 219 | 220 | /** 221 | `AFImageResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes image responses. 222 | 223 | By default, `AFImageResponseSerializer` accepts the following MIME types, which correspond to the image formats supported by UIImage or NSImage: 224 | 225 | - `image/tiff` 226 | - `image/jpeg` 227 | - `image/gif` 228 | - `image/png` 229 | - `image/ico` 230 | - `image/x-icon` 231 | - `image/bmp` 232 | - `image/x-bmp` 233 | - `image/x-xbitmap` 234 | - `image/x-win-bitmap` 235 | */ 236 | @interface AFImageResponseSerializer : AFHTTPResponseSerializer 237 | 238 | #if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH 239 | /** 240 | The scale factor used when interpreting the image data to construct `responseImage`. Specifying a scale factor of 1.0 results in an image whose size matches the pixel-based dimensions of the image. Applying a different scale factor changes the size of the image as reported by the size property. This is set to the value of scale of the main screen by default, which automatically scales images for retina displays, for instance. 241 | */ 242 | @property (nonatomic, assign) CGFloat imageScale; 243 | 244 | /** 245 | Whether to automatically inflate response image data for compressed formats (such as PNG or JPEG). Enabling this can significantly improve drawing performance on iOS when used with `setCompletionBlockWithSuccess:failure:`, as it allows a bitmap representation to be constructed in the background rather than on the main thread. `YES` by default. 246 | */ 247 | @property (nonatomic, assign) BOOL automaticallyInflatesResponseImage; 248 | #endif 249 | 250 | @end 251 | 252 | #pragma mark - 253 | 254 | /** 255 | `AFCompoundSerializer` is a subclass of `AFHTTPResponseSerializer` that delegates the response serialization to the first `AFHTTPResponseSerializer` object that returns an object for `responseObjectForResponse:data:error:`, falling back on the default behavior of `AFHTTPResponseSerializer`. This is useful for supporting multiple potential types and structures of server responses with a single serializer. 256 | */ 257 | @interface AFCompoundResponseSerializer : AFHTTPResponseSerializer 258 | 259 | /** 260 | The component response serializers. 261 | */ 262 | @property (readonly, nonatomic, copy) NSArray > *responseSerializers; 263 | 264 | /** 265 | Creates and returns a compound serializer comprised of the specified response serializers. 266 | 267 | @warning Each response serializer specified must be a subclass of `AFHTTPResponseSerializer`, and response to `-validateResponse:data:error:`. 268 | */ 269 | + (instancetype)compoundSerializerWithResponseSerializers:(NSArray > *)responseSerializers; 270 | 271 | @end 272 | 273 | ///---------------- 274 | /// @name Constants 275 | ///---------------- 276 | 277 | /** 278 | ## Error Domains 279 | 280 | The following error domain is predefined. 281 | 282 | - `NSString * const AFURLResponseSerializationErrorDomain` 283 | 284 | ### Constants 285 | 286 | `AFURLResponseSerializationErrorDomain` 287 | AFURLResponseSerializer errors. Error codes for `AFURLResponseSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`. 288 | */ 289 | FOUNDATION_EXPORT NSString * const AFURLResponseSerializationErrorDomain; 290 | 291 | /** 292 | ## User info dictionary keys 293 | 294 | These keys may exist in the user info dictionary, in addition to those defined for NSError. 295 | 296 | - `NSString * const AFNetworkingOperationFailingURLResponseErrorKey` 297 | - `NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey` 298 | 299 | ### Constants 300 | 301 | `AFNetworkingOperationFailingURLResponseErrorKey` 302 | The corresponding value is an `NSURLResponse` containing the response of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. 303 | 304 | `AFNetworkingOperationFailingURLResponseDataErrorKey` 305 | The corresponding value is an `NSData` containing the original data of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. 306 | */ 307 | FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseErrorKey; 308 | 309 | FOUNDATION_EXPORT NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey; 310 | 311 | NS_ASSUME_NONNULL_END 312 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/AFNetworking/AFSecurityPolicy.m: -------------------------------------------------------------------------------- 1 | // AFSecurityPolicy.m 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "AFSecurityPolicy.h" 23 | 24 | #import 25 | 26 | #if !TARGET_OS_IOS && !TARGET_OS_WATCH && !TARGET_OS_TV 27 | static NSData * AFSecKeyGetData(SecKeyRef key) { 28 | CFDataRef data = NULL; 29 | 30 | __Require_noErr_Quiet(SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data), _out); 31 | 32 | return (__bridge_transfer NSData *)data; 33 | 34 | _out: 35 | if (data) { 36 | CFRelease(data); 37 | } 38 | 39 | return nil; 40 | } 41 | #endif 42 | 43 | static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) { 44 | #if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_TV 45 | return [(__bridge id)key1 isEqual:(__bridge id)key2]; 46 | #else 47 | return [AFSecKeyGetData(key1) isEqual:AFSecKeyGetData(key2)]; 48 | #endif 49 | } 50 | 51 | static id AFPublicKeyForCertificate(NSData *certificate) { 52 | id allowedPublicKey = nil; 53 | SecCertificateRef allowedCertificate; 54 | SecCertificateRef allowedCertificates[1]; 55 | CFArrayRef tempCertificates = nil; 56 | SecPolicyRef policy = nil; 57 | SecTrustRef allowedTrust = nil; 58 | SecTrustResultType result; 59 | 60 | allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate); 61 | __Require_Quiet(allowedCertificate != NULL, _out); 62 | 63 | allowedCertificates[0] = allowedCertificate; 64 | tempCertificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL); 65 | 66 | policy = SecPolicyCreateBasicX509(); 67 | __Require_noErr_Quiet(SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust), _out); 68 | __Require_noErr_Quiet(SecTrustEvaluate(allowedTrust, &result), _out); 69 | 70 | allowedPublicKey = (__bridge_transfer id)SecTrustCopyPublicKey(allowedTrust); 71 | 72 | _out: 73 | if (allowedTrust) { 74 | CFRelease(allowedTrust); 75 | } 76 | 77 | if (policy) { 78 | CFRelease(policy); 79 | } 80 | 81 | if (tempCertificates) { 82 | CFRelease(tempCertificates); 83 | } 84 | 85 | if (allowedCertificate) { 86 | CFRelease(allowedCertificate); 87 | } 88 | 89 | return allowedPublicKey; 90 | } 91 | 92 | static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) { 93 | BOOL isValid = NO; 94 | SecTrustResultType result; 95 | __Require_noErr_Quiet(SecTrustEvaluate(serverTrust, &result), _out); 96 | 97 | isValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); 98 | 99 | _out: 100 | return isValid; 101 | } 102 | 103 | static NSArray * AFCertificateTrustChainForServerTrust(SecTrustRef serverTrust) { 104 | CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); 105 | NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; 106 | 107 | for (CFIndex i = 0; i < certificateCount; i++) { 108 | SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); 109 | [trustChain addObject:(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]; 110 | } 111 | 112 | return [NSArray arrayWithArray:trustChain]; 113 | } 114 | 115 | static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { 116 | SecPolicyRef policy = SecPolicyCreateBasicX509(); 117 | CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); 118 | NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; 119 | for (CFIndex i = 0; i < certificateCount; i++) { 120 | SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); 121 | 122 | SecCertificateRef someCertificates[] = {certificate}; 123 | CFArrayRef certificates = CFArrayCreate(NULL, (const void **)someCertificates, 1, NULL); 124 | 125 | SecTrustRef trust; 126 | __Require_noErr_Quiet(SecTrustCreateWithCertificates(certificates, policy, &trust), _out); 127 | 128 | SecTrustResultType result; 129 | __Require_noErr_Quiet(SecTrustEvaluate(trust, &result), _out); 130 | 131 | [trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)]; 132 | 133 | _out: 134 | if (trust) { 135 | CFRelease(trust); 136 | } 137 | 138 | if (certificates) { 139 | CFRelease(certificates); 140 | } 141 | 142 | continue; 143 | } 144 | CFRelease(policy); 145 | 146 | return [NSArray arrayWithArray:trustChain]; 147 | } 148 | 149 | #pragma mark - 150 | 151 | @interface AFSecurityPolicy() 152 | @property (readwrite, nonatomic, assign) AFSSLPinningMode SSLPinningMode; 153 | @property (readwrite, nonatomic, strong) NSSet *pinnedPublicKeys; 154 | @end 155 | 156 | @implementation AFSecurityPolicy 157 | 158 | + (NSSet *)certificatesInBundle:(NSBundle *)bundle { 159 | NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."]; 160 | 161 | NSMutableSet *certificates = [NSMutableSet setWithCapacity:[paths count]]; 162 | for (NSString *path in paths) { 163 | NSData *certificateData = [NSData dataWithContentsOfFile:path]; 164 | [certificates addObject:certificateData]; 165 | } 166 | 167 | return [NSSet setWithSet:certificates]; 168 | } 169 | 170 | + (NSSet *)defaultPinnedCertificates { 171 | static NSSet *_defaultPinnedCertificates = nil; 172 | static dispatch_once_t onceToken; 173 | dispatch_once(&onceToken, ^{ 174 | NSBundle *bundle = [NSBundle bundleForClass:[self class]]; 175 | _defaultPinnedCertificates = [self certificatesInBundle:bundle]; 176 | }); 177 | 178 | return _defaultPinnedCertificates; 179 | } 180 | 181 | + (instancetype)defaultPolicy { 182 | AFSecurityPolicy *securityPolicy = [[self alloc] init]; 183 | securityPolicy.SSLPinningMode = AFSSLPinningModeNone; 184 | 185 | return securityPolicy; 186 | } 187 | 188 | + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode { 189 | return [self policyWithPinningMode:pinningMode withPinnedCertificates:[self defaultPinnedCertificates]]; 190 | } 191 | 192 | + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode withPinnedCertificates:(NSSet *)pinnedCertificates { 193 | AFSecurityPolicy *securityPolicy = [[self alloc] init]; 194 | securityPolicy.SSLPinningMode = pinningMode; 195 | 196 | [securityPolicy setPinnedCertificates:pinnedCertificates]; 197 | 198 | return securityPolicy; 199 | } 200 | 201 | - (instancetype)init { 202 | self = [super init]; 203 | if (!self) { 204 | return nil; 205 | } 206 | 207 | self.validatesDomainName = YES; 208 | 209 | return self; 210 | } 211 | 212 | - (void)setPinnedCertificates:(NSSet *)pinnedCertificates { 213 | _pinnedCertificates = pinnedCertificates; 214 | 215 | if (self.pinnedCertificates) { 216 | NSMutableSet *mutablePinnedPublicKeys = [NSMutableSet setWithCapacity:[self.pinnedCertificates count]]; 217 | for (NSData *certificate in self.pinnedCertificates) { 218 | id publicKey = AFPublicKeyForCertificate(certificate); 219 | if (!publicKey) { 220 | continue; 221 | } 222 | [mutablePinnedPublicKeys addObject:publicKey]; 223 | } 224 | self.pinnedPublicKeys = [NSSet setWithSet:mutablePinnedPublicKeys]; 225 | } else { 226 | self.pinnedPublicKeys = nil; 227 | } 228 | } 229 | 230 | #pragma mark - 231 | 232 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust 233 | forDomain:(NSString *)domain 234 | { 235 | if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == AFSSLPinningModeNone || [self.pinnedCertificates count] == 0)) { 236 | // https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html 237 | // According to the docs, you should only trust your provided certs for evaluation. 238 | // Pinned certificates are added to the trust. Without pinned certificates, 239 | // there is nothing to evaluate against. 240 | // 241 | // From Apple Docs: 242 | // "Do not implicitly trust self-signed certificates as anchors (kSecTrustOptionImplicitAnchors). 243 | // Instead, add your own (self-signed) CA certificate to the list of trusted anchors." 244 | NSLog(@"In order to validate a domain name for self signed certificates, you MUST use pinning."); 245 | return NO; 246 | } 247 | 248 | NSMutableArray *policies = [NSMutableArray array]; 249 | if (self.validatesDomainName) { 250 | [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)]; 251 | } else { 252 | [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()]; 253 | } 254 | 255 | SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies); 256 | 257 | if (self.SSLPinningMode == AFSSLPinningModeNone) { 258 | return self.allowInvalidCertificates || AFServerTrustIsValid(serverTrust); 259 | } else if (!AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) { 260 | return NO; 261 | } 262 | 263 | switch (self.SSLPinningMode) { 264 | case AFSSLPinningModeNone: 265 | default: 266 | return NO; 267 | case AFSSLPinningModeCertificate: { 268 | NSMutableArray *pinnedCertificates = [NSMutableArray array]; 269 | for (NSData *certificateData in self.pinnedCertificates) { 270 | [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)]; 271 | } 272 | SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates); 273 | 274 | if (!AFServerTrustIsValid(serverTrust)) { 275 | return NO; 276 | } 277 | 278 | // obtain the chain after being validated, which *should* contain the pinned certificate in the last position (if it's the Root CA) 279 | NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust); 280 | 281 | for (NSData *trustChainCertificate in [serverCertificates reverseObjectEnumerator]) { 282 | if ([self.pinnedCertificates containsObject:trustChainCertificate]) { 283 | return YES; 284 | } 285 | } 286 | 287 | return NO; 288 | } 289 | case AFSSLPinningModePublicKey: { 290 | NSUInteger trustedPublicKeyCount = 0; 291 | NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust); 292 | 293 | for (id trustChainPublicKey in publicKeys) { 294 | for (id pinnedPublicKey in self.pinnedPublicKeys) { 295 | if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) { 296 | trustedPublicKeyCount += 1; 297 | } 298 | } 299 | } 300 | return trustedPublicKeyCount > 0; 301 | } 302 | } 303 | 304 | return NO; 305 | } 306 | 307 | #pragma mark - NSKeyValueObserving 308 | 309 | + (NSSet *)keyPathsForValuesAffectingPinnedPublicKeys { 310 | return [NSSet setWithObject:@"pinnedCertificates"]; 311 | } 312 | 313 | #pragma mark - NSSecureCoding 314 | 315 | + (BOOL)supportsSecureCoding { 316 | return YES; 317 | } 318 | 319 | - (instancetype)initWithCoder:(NSCoder *)decoder { 320 | 321 | self = [self init]; 322 | if (!self) { 323 | return nil; 324 | } 325 | 326 | self.SSLPinningMode = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(SSLPinningMode))] unsignedIntegerValue]; 327 | self.allowInvalidCertificates = [decoder decodeBoolForKey:NSStringFromSelector(@selector(allowInvalidCertificates))]; 328 | self.validatesDomainName = [decoder decodeBoolForKey:NSStringFromSelector(@selector(validatesDomainName))]; 329 | self.pinnedCertificates = [decoder decodeObjectOfClass:[NSArray class] forKey:NSStringFromSelector(@selector(pinnedCertificates))]; 330 | 331 | return self; 332 | } 333 | 334 | - (void)encodeWithCoder:(NSCoder *)coder { 335 | [coder encodeObject:[NSNumber numberWithUnsignedInteger:self.SSLPinningMode] forKey:NSStringFromSelector(@selector(SSLPinningMode))]; 336 | [coder encodeBool:self.allowInvalidCertificates forKey:NSStringFromSelector(@selector(allowInvalidCertificates))]; 337 | [coder encodeBool:self.validatesDomainName forKey:NSStringFromSelector(@selector(validatesDomainName))]; 338 | [coder encodeObject:self.pinnedCertificates forKey:NSStringFromSelector(@selector(pinnedCertificates))]; 339 | } 340 | 341 | #pragma mark - NSCopying 342 | 343 | - (instancetype)copyWithZone:(NSZone *)zone { 344 | AFSecurityPolicy *securityPolicy = [[[self class] allocWithZone:zone] init]; 345 | securityPolicy.SSLPinningMode = self.SSLPinningMode; 346 | securityPolicy.allowInvalidCertificates = self.allowInvalidCertificates; 347 | securityPolicy.validatesDomainName = self.validatesDomainName; 348 | securityPolicy.pinnedCertificates = [self.pinnedCertificates copyWithZone:zone]; 349 | 350 | return securityPolicy; 351 | } 352 | 353 | @end 354 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/TYJSONModel/NSObject+TYJSONModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+TYJSONModel.m 3 | // TYJSONModelDemo 4 | // 5 | // Created by tany on 16/4/6. 6 | // Copyright © 2016年 tany. All rights reserved. 7 | // 8 | 9 | #import "NSObject+TYJSONModel.h" 10 | #import "TYClassInfo.h" 11 | #import 12 | 13 | 14 | @implementation NSObject (TYJSONModel) 15 | 16 | #pragma mark - json to model 17 | 18 | + (instancetype)ty_ModelWithJSON:(id)json 19 | { 20 | if (!json) { 21 | return nil; 22 | } 23 | 24 | NSDictionary *dic = nil; 25 | NSData *jsonData = nil; 26 | if ([json isKindOfClass:[NSDictionary class]]) { 27 | dic = json; 28 | } else if ([json isKindOfClass:[NSString class]]) { 29 | jsonData = [(NSString *)json dataUsingEncoding : NSUTF8StringEncoding]; 30 | } else if ([json isKindOfClass:[NSData class]]) { 31 | jsonData = json; 32 | } 33 | if (jsonData) { 34 | // data to json 35 | dic = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:NULL]; 36 | if (![dic isKindOfClass:[NSDictionary class]]) 37 | dic = nil; 38 | } 39 | 40 | return [self ty_ModelWithDictonary:dic]; 41 | } 42 | 43 | // dictonary to model 44 | + (instancetype)ty_ModelWithDictonary:(NSDictionary *)dic 45 | { 46 | if (!dic) { 47 | return nil; 48 | } 49 | 50 | NSObject *model = [[[self class]alloc]init]; 51 | 52 | // dictonary to model 53 | [model ty_SetModelWithDictonary:dic]; 54 | 55 | return model; 56 | } 57 | 58 | // dictonary to model 59 | - (void)ty_SetModelWithDictonary:(NSDictionary *)dic 60 | { 61 | if (!dic || ![dic isKindOfClass:[NSDictionary class]] || dic.count == 0) { 62 | return; 63 | } 64 | 65 | // 获取 当前类信息 66 | TYClassInfo *classInfo = [[TYClassInfo alloc]initWithClass:object_getClass(self)]; 67 | 68 | // model in array or dictonary 映射 69 | NSDictionary *modelClassDic = nil; 70 | if ([[self class] respondsToSelector:@selector(modelClassInArrayOrDictonary)]) { 71 | modelClassDic = [[self class] modelClassInArrayOrDictonary]; 72 | } 73 | 74 | // 属性 映射 75 | NSDictionary *propertyMapper = nil; 76 | if ([[self class] respondsToSelector:@selector(modelPropertyMapper)]) { 77 | propertyMapper = [[self class] modelPropertyMapper]; 78 | } 79 | 80 | // 忽略 某些属性 81 | NSArray *ignoreProperties = nil; 82 | if ([[self class] respondsToSelector:@selector(ignoreModelProperties)]) { 83 | ignoreProperties = [[self class] ignoreModelProperties]; 84 | } 85 | 86 | // 遍历当前类所有属性 87 | [classInfo.propertyInfo enumerateKeysAndObjectsUsingBlock:^(NSString *key, TYPropertyInfo *propertyInfo, BOOL * stop) { 88 | 89 | BOOL isIgnoreProperty = NO; 90 | id value = nil; 91 | 92 | if (ignoreProperties) { 93 | // 是否忽略这个属性 94 | isIgnoreProperty = [ignoreProperties containsObject:key]; 95 | } 96 | 97 | if (!isIgnoreProperty) { 98 | NSString *maperKey = nil; //映射key 99 | if (propertyMapper) { 100 | maperKey = [propertyMapper objectForKey:key]; 101 | } 102 | 103 | // 根据属性名key 获取 字典里的value 104 | value = [dic objectForKey:maperKey ? maperKey : key]; 105 | } 106 | 107 | if (!isIgnoreProperty && value) { 108 | // 如果value有值 109 | if ([value isKindOfClass:[NSArray class]]) { 110 | // 校验 property 是否 数组类型 111 | if ([propertyInfo.typeClass isSubclassOfClass:[NSArray class]]) { 112 | Class class = nil; 113 | if (modelClassDic) { 114 | // 数组里是否包含模型 115 | class = [modelClassDic objectForKey:key]; 116 | } 117 | if (class) { 118 | // 包含 就调用数组的 转模型方法 119 | value = [(NSArray *)value ty_ModelArrayWithClass:class]; 120 | } 121 | }else { 122 | // property 不是数组类型 返回数据有误 123 | value = nil; 124 | } 125 | }else if([value isKindOfClass:[NSDictionary class]]){ 126 | // property 是否是自定义模型 127 | if (propertyInfo.isCustomFondation) { 128 | // 字典 对应模型 129 | value = [propertyInfo.typeClass ty_ModelWithDictonary:value]; 130 | }else if ([propertyInfo.typeClass isSubclassOfClass:[NSDictionary class]]) { 131 | // property 是 字典类型 132 | if (modelClassDic) { 133 | // 字典 里 是否包含模型 134 | Class class = [modelClassDic objectForKey:key]; 135 | if (class) { 136 | // 包含 就调用字典的 转模型方法 137 | value = [(NSDictionary *)value ty_ModelDictionaryWithClass:class]; 138 | } 139 | } 140 | }else { 141 | // property 不是 字典类型 返回数据有误 142 | value = nil; 143 | } 144 | } 145 | 146 | if ([value isEqual:[NSNull null]]) { 147 | // 去除 null 148 | value = nil; 149 | } 150 | 151 | if (propertyInfo.typeClass) { 152 | // 对象类型 153 | if ([propertyInfo.typeClass isSubclassOfClass:[NSString class]] && [value isKindOfClass:[NSNumber class]]) { 154 | // number 转 string 155 | value = [(NSNumber *)value stringValue]; 156 | }else if (propertyInfo.typeClass == [NSValue class] || propertyInfo.typeClass == [NSDate class]) { 157 | // 不支持类型 158 | value = nil; 159 | } 160 | // 调用生成的 setter 方法 设置值 161 | [self setPropertyWithModel:self value:value setter:propertyInfo.setter]; 162 | }else if(value) { 163 | // 基本类型 164 | if ([value isKindOfClass:[NSString class]]) { 165 | static NSNumberFormatter *s_numberFormatter; 166 | static dispatch_once_t onceToken; 167 | dispatch_once(&onceToken, ^{ 168 | // NSString 转 NSNumber Formatter 169 | s_numberFormatter = [[NSNumberFormatter alloc]init]; 170 | }); 171 | // string 转 number 172 | value = [s_numberFormatter numberFromString:value]; 173 | } 174 | // kvc 设置基本类型的值 175 | [self setValue:value forKey:key]; 176 | } 177 | } 178 | }]; 179 | } 180 | 181 | // model to dictonary 182 | - (NSDictionary *)ty_ModelToDictonary 183 | { 184 | if ([self isKindOfClass:[NSArray class]]) { 185 | return nil; 186 | } 187 | 188 | // 属性 映射 189 | NSDictionary *propertyMapper = nil; 190 | if ([[self class] respondsToSelector:@selector(modelPropertyMapper)]) { 191 | propertyMapper = [[self class] modelPropertyMapper]; 192 | } 193 | 194 | // 忽略 某些属性 195 | NSArray *ignoreProperties = nil; 196 | if ([[self class] respondsToSelector:@selector(ignoreModelProperties)]) { 197 | ignoreProperties = [[self class] ignoreModelProperties]; 198 | } 199 | 200 | // 获取 当前类信息 201 | TYClassInfo *classInfo = [[TYClassInfo alloc]initWithClass:object_getClass(self)]; 202 | // 字典 203 | NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:classInfo.propertyInfo.count]; 204 | 205 | [classInfo.propertyInfo enumerateKeysAndObjectsUsingBlock:^(NSString *key, TYPropertyInfo *propertyInfo, BOOL * stop) { 206 | 207 | BOOL isIgnoreProperty = NO; 208 | id value = nil; 209 | 210 | if (ignoreProperties) { 211 | // 是否忽略这个属性 212 | isIgnoreProperty = [ignoreProperties containsObject:key]; 213 | } 214 | 215 | if (!isIgnoreProperty) { 216 | if (propertyInfo.typeClass) { 217 | // 对象类型 调用生成的 getter 方法 获取值 218 | value = [self propertyValueWithModel:self getter:propertyInfo.getter]; 219 | }else { 220 | // 基本类型 使用kvc 获取值 221 | value = [self valueForKey:key]; 222 | } 223 | } 224 | 225 | if (!isIgnoreProperty && value) { 226 | // 如果有值 227 | if ([value isKindOfClass:[NSArray class]]) { 228 | // 如果值是数组(可能包含模型) 调用model数组转dic数组方法 229 | value = [(NSArray *)value ty_ModelArrayToDicArray]; 230 | }else if ([value isKindOfClass:[NSDictionary class]]) { 231 | // 如果值是字典(可能包含模型) 调用字典 model转dic方法 232 | value = [(NSDictionary *)value ty_ModelDictionaryToDictionary]; 233 | }else if (propertyInfo.typeClass && propertyInfo.isCustomFondation) { 234 | value = [value ty_ModelToDictonary]; 235 | } 236 | 237 | if (value) { 238 | NSString *maperKey = nil; 239 | if (propertyMapper) { 240 | //映射key 241 | maperKey = [propertyMapper objectForKey:key]; 242 | } 243 | // 添加到字典 244 | dic[maperKey ? maperKey : key] = value; 245 | } 246 | 247 | } 248 | 249 | }]; 250 | 251 | return [dic copy]; 252 | } 253 | 254 | // dic array to model array 255 | + (NSArray *)ty_modelArrayWithDictionaryArray:(NSArray *)dicArray 256 | { 257 | return [dicArray ty_ModelArrayWithClass:[self class]]; 258 | } 259 | 260 | #pragma mark - model to json 261 | // model to json 262 | - (id)ty_ModelToJSONObject 263 | { 264 | if ([self isKindOfClass:[NSArray class]]) { 265 | // 如果是数组 266 | return [(NSArray *)self ty_ModelArrayToDicArray]; 267 | } 268 | 269 | return [self ty_ModelToDictonary]; 270 | } 271 | 272 | - (NSData *)ty_ModelToJSONData 273 | { 274 | id jsonObject = [self ty_ModelToJSONObject]; 275 | if (!jsonObject) return nil; 276 | return [NSJSONSerialization dataWithJSONObject:jsonObject options:0 error:NULL]; 277 | } 278 | 279 | - (NSString *)ty_ModelToJSONString 280 | { 281 | NSData *jsonData = [self ty_ModelToJSONData]; 282 | if (jsonData.length == 0) return nil; 283 | return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 284 | } 285 | 286 | // model array to dic array 287 | + (NSArray *)ty_dictionaryArrayWithModelArray:(NSArray *)dicArray 288 | { 289 | return [dicArray ty_ModelArrayToDicArray]; 290 | } 291 | 292 | #pragma mark - encode decode 293 | // encode 294 | - (void)ty_EncodeWithCoder:(NSCoder *)aCoder 295 | { 296 | TYClassInfo *classInfo = [[TYClassInfo alloc]initWithClass:object_getClass(self)]; 297 | 298 | [classInfo.propertyInfo enumerateKeysAndObjectsUsingBlock:^(NSString *key, TYPropertyInfo *propertyInfo, BOOL * stop) { 299 | 300 | id value = nil; 301 | 302 | if (propertyInfo.typeClass) { 303 | value = [self propertyValueWithModel:self getter:propertyInfo.getter]; 304 | 305 | }else { 306 | value = [self valueForKey:key]; 307 | } 308 | 309 | if (value) { 310 | [aCoder encodeObject:value forKey:key]; 311 | } 312 | }]; 313 | } 314 | 315 | // decode 316 | - (instancetype)ty_InitWithCoder:(NSCoder *)aDecoder 317 | { 318 | if ([self init]) { 319 | TYClassInfo *classInfo = [[TYClassInfo alloc]initWithClass:object_getClass(self)]; 320 | 321 | [classInfo.propertyInfo enumerateKeysAndObjectsUsingBlock:^(NSString *key, TYPropertyInfo *propertyInfo, BOOL * stop) { 322 | 323 | id value = [aDecoder decodeObjectForKey:key]; 324 | 325 | if (value) { 326 | if (propertyInfo.typeClass) { 327 | [self setPropertyWithModel:self value:value setter:propertyInfo.setter]; 328 | }else { 329 | [self setValue:value forKey:key]; 330 | } 331 | } 332 | }]; 333 | } 334 | return self; 335 | } 336 | 337 | #pragma mark - set get Property 338 | 339 | // set Property 340 | - (void)setPropertyWithModel:(id)model value:(id)value setter:(SEL)setter 341 | { 342 | if (!setter) { 343 | return; 344 | } 345 | ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, setter, value); 346 | } 347 | 348 | // get Property 349 | - (id)propertyValueWithModel:(id)model getter:(SEL)getter 350 | { 351 | if (!getter) { 352 | return nil; 353 | } 354 | return ((id (*)(id, SEL))(void *) objc_msgSend)((id)model,getter); 355 | } 356 | 357 | @end 358 | 359 | @implementation NSArray (TYJSONModel) 360 | 361 | // 数组 to model 数组 362 | - (NSArray *)ty_ModelArrayWithClass:(Class)class 363 | { 364 | if (!class) { 365 | return self; 366 | } 367 | NSMutableArray *modelArray = [NSMutableArray array]; 368 | // 遍历数组 369 | for (id value in self) { 370 | 371 | if ([value isKindOfClass:[NSDictionary class]]) { 372 | // value是字典 则 字典转模型 373 | NSObject *obj = [class ty_ModelWithDictonary:value]; 374 | if (obj) { 375 | [modelArray addObject:obj]; 376 | } 377 | }else if ([value isKindOfClass:[NSString class]]) { 378 | // value 是 NSString 379 | [modelArray addObject:value]; 380 | } 381 | } 382 | return [modelArray copy]; 383 | } 384 | 385 | // model 数组 to 数组 386 | - (NSArray *)ty_ModelArrayToDicArray 387 | { 388 | NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.count]; 389 | // 遍历数组 390 | for (id obj in self) { 391 | if (![TYPropertyInfo isClassFromFoundation:[obj class]]) { 392 | // obj 是 model 则 model 转 字典 393 | NSDictionary *dic = [obj ty_ModelToDictonary]; 394 | if (dic) { 395 | [array addObject:dic]; 396 | } 397 | }else { 398 | [array addObject:obj]; 399 | } 400 | } 401 | return [array copy]; 402 | } 403 | 404 | @end 405 | 406 | @implementation NSDictionary (TYJSONModel) 407 | 408 | // 字典 to model 字典 409 | - (NSDictionary *)ty_ModelDictionaryWithClass:(Class)class 410 | { 411 | if (!class) { 412 | return self; 413 | } 414 | 415 | NSMutableDictionary *dic = [NSMutableDictionary dictionary]; 416 | // 遍历字典 417 | [self enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL * stop) { 418 | if ([key isKindOfClass:[NSString class]]) { 419 | // 字典包含 obj字典 转 model 420 | NSObject *value = [class ty_ModelWithDictonary:obj]; 421 | if (value) { 422 | dic[key] = value; 423 | } 424 | } 425 | }]; 426 | return [dic copy]; 427 | 428 | } 429 | 430 | // model 字典 to 字典 431 | - (NSDictionary *)ty_ModelDictionaryToDictionary 432 | { 433 | NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:self.count]; 434 | // 遍历字典 435 | [self enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL * stop) { 436 | if (![TYPropertyInfo isClassFromFoundation:[obj class]]) { 437 | // obj 是 模型 则 model to dic 438 | NSDictionary *objDic = [obj ty_ModelToDictonary]; 439 | if (objDic) { 440 | dic[key] = objDic; 441 | } 442 | }else { 443 | dic[key] = obj; 444 | } 445 | }]; 446 | return [dic copy]; 447 | } 448 | 449 | @end 450 | 451 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/AFNetworking/AFHTTPSessionManager.m: -------------------------------------------------------------------------------- 1 | // AFHTTPSessionManager.m 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import "AFHTTPSessionManager.h" 23 | 24 | #import "AFURLRequestSerialization.h" 25 | #import "AFURLResponseSerialization.h" 26 | 27 | #import 28 | #import 29 | #import 30 | 31 | #import 32 | #import 33 | #import 34 | #import 35 | #import 36 | 37 | #if TARGET_OS_IOS || TARGET_OS_TV 38 | #import 39 | #elif TARGET_OS_WATCH 40 | #import 41 | #endif 42 | 43 | @interface AFHTTPSessionManager () 44 | @property (readwrite, nonatomic, strong) NSURL *baseURL; 45 | @end 46 | 47 | @implementation AFHTTPSessionManager 48 | @dynamic responseSerializer; 49 | 50 | + (instancetype)manager { 51 | return [[[self class] alloc] initWithBaseURL:nil]; 52 | } 53 | 54 | - (instancetype)init { 55 | return [self initWithBaseURL:nil]; 56 | } 57 | 58 | - (instancetype)initWithBaseURL:(NSURL *)url { 59 | return [self initWithBaseURL:url sessionConfiguration:nil]; 60 | } 61 | 62 | - (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration { 63 | return [self initWithBaseURL:nil sessionConfiguration:configuration]; 64 | } 65 | 66 | - (instancetype)initWithBaseURL:(NSURL *)url 67 | sessionConfiguration:(NSURLSessionConfiguration *)configuration 68 | { 69 | self = [super initWithSessionConfiguration:configuration]; 70 | if (!self) { 71 | return nil; 72 | } 73 | 74 | // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected 75 | if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) { 76 | url = [url URLByAppendingPathComponent:@""]; 77 | } 78 | 79 | self.baseURL = url; 80 | 81 | self.requestSerializer = [AFHTTPRequestSerializer serializer]; 82 | self.responseSerializer = [AFJSONResponseSerializer serializer]; 83 | 84 | return self; 85 | } 86 | 87 | #pragma mark - 88 | 89 | - (void)setRequestSerializer:(AFHTTPRequestSerializer *)requestSerializer { 90 | NSParameterAssert(requestSerializer); 91 | 92 | _requestSerializer = requestSerializer; 93 | } 94 | 95 | - (void)setResponseSerializer:(AFHTTPResponseSerializer *)responseSerializer { 96 | NSParameterAssert(responseSerializer); 97 | 98 | [super setResponseSerializer:responseSerializer]; 99 | } 100 | 101 | #pragma mark - 102 | 103 | - (NSURLSessionDataTask *)GET:(NSString *)URLString 104 | parameters:(id)parameters 105 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 106 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 107 | { 108 | 109 | return [self GET:URLString parameters:parameters progress:nil success:success failure:failure]; 110 | } 111 | 112 | - (NSURLSessionDataTask *)GET:(NSString *)URLString 113 | parameters:(id)parameters 114 | progress:(void (^)(NSProgress * _Nonnull))downloadProgress 115 | success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success 116 | failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure 117 | { 118 | 119 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET" 120 | URLString:URLString 121 | parameters:parameters 122 | uploadProgress:nil 123 | downloadProgress:downloadProgress 124 | success:success 125 | failure:failure]; 126 | 127 | [dataTask resume]; 128 | 129 | return dataTask; 130 | } 131 | 132 | - (NSURLSessionDataTask *)HEAD:(NSString *)URLString 133 | parameters:(id)parameters 134 | success:(void (^)(NSURLSessionDataTask *task))success 135 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 136 | { 137 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:^(NSURLSessionDataTask *task, __unused id responseObject) { 138 | if (success) { 139 | success(task); 140 | } 141 | } failure:failure]; 142 | 143 | [dataTask resume]; 144 | 145 | return dataTask; 146 | } 147 | 148 | - (NSURLSessionDataTask *)POST:(NSString *)URLString 149 | parameters:(id)parameters 150 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 151 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 152 | { 153 | return [self POST:URLString parameters:parameters progress:nil success:success failure:failure]; 154 | } 155 | 156 | - (NSURLSessionDataTask *)POST:(NSString *)URLString 157 | parameters:(id)parameters 158 | progress:(void (^)(NSProgress * _Nonnull))uploadProgress 159 | success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success 160 | failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure 161 | { 162 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure]; 163 | 164 | [dataTask resume]; 165 | 166 | return dataTask; 167 | } 168 | 169 | - (NSURLSessionDataTask *)POST:(NSString *)URLString 170 | parameters:(nullable id)parameters 171 | constructingBodyWithBlock:(nullable void (^)(id _Nonnull))block 172 | success:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success 173 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure 174 | { 175 | return [self POST:URLString parameters:parameters constructingBodyWithBlock:block progress:nil success:success failure:failure]; 176 | } 177 | 178 | - (NSURLSessionDataTask *)POST:(NSString *)URLString 179 | parameters:(id)parameters 180 | constructingBodyWithBlock:(void (^)(id formData))block 181 | progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress 182 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 183 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 184 | { 185 | NSError *serializationError = nil; 186 | NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError]; 187 | if (serializationError) { 188 | if (failure) { 189 | dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ 190 | failure(nil, serializationError); 191 | }); 192 | } 193 | 194 | return nil; 195 | } 196 | 197 | __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:uploadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { 198 | if (error) { 199 | if (failure) { 200 | failure(task, error); 201 | } 202 | } else { 203 | if (success) { 204 | success(task, responseObject); 205 | } 206 | } 207 | }]; 208 | 209 | [task resume]; 210 | 211 | return task; 212 | } 213 | 214 | - (NSURLSessionDataTask *)PUT:(NSString *)URLString 215 | parameters:(id)parameters 216 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 217 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 218 | { 219 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure]; 220 | 221 | [dataTask resume]; 222 | 223 | return dataTask; 224 | } 225 | 226 | - (NSURLSessionDataTask *)PATCH:(NSString *)URLString 227 | parameters:(id)parameters 228 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 229 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 230 | { 231 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure]; 232 | 233 | [dataTask resume]; 234 | 235 | return dataTask; 236 | } 237 | 238 | - (NSURLSessionDataTask *)DELETE:(NSString *)URLString 239 | parameters:(id)parameters 240 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 241 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 242 | { 243 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure]; 244 | 245 | [dataTask resume]; 246 | 247 | return dataTask; 248 | } 249 | 250 | - (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method 251 | URLString:(NSString *)URLString 252 | parameters:(id)parameters 253 | uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress 254 | downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress 255 | success:(void (^)(NSURLSessionDataTask *, id))success 256 | failure:(void (^)(NSURLSessionDataTask *, NSError *))failure 257 | { 258 | NSError *serializationError = nil; 259 | NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError]; 260 | if (serializationError) { 261 | if (failure) { 262 | dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ 263 | failure(nil, serializationError); 264 | }); 265 | } 266 | 267 | return nil; 268 | } 269 | 270 | __block NSURLSessionDataTask *dataTask = nil; 271 | dataTask = [self dataTaskWithRequest:request 272 | uploadProgress:uploadProgress 273 | downloadProgress:downloadProgress 274 | completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { 275 | if (error) { 276 | if (failure) { 277 | failure(dataTask, error); 278 | } 279 | } else { 280 | if (success) { 281 | success(dataTask, responseObject); 282 | } 283 | } 284 | }]; 285 | 286 | return dataTask; 287 | } 288 | 289 | #pragma mark - NSObject 290 | 291 | - (NSString *)description { 292 | return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.session, self.operationQueue]; 293 | } 294 | 295 | #pragma mark - NSSecureCoding 296 | 297 | + (BOOL)supportsSecureCoding { 298 | return YES; 299 | } 300 | 301 | - (instancetype)initWithCoder:(NSCoder *)decoder { 302 | NSURL *baseURL = [decoder decodeObjectOfClass:[NSURL class] forKey:NSStringFromSelector(@selector(baseURL))]; 303 | NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"]; 304 | if (!configuration) { 305 | NSString *configurationIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"identifier"]; 306 | if (configurationIdentifier) { 307 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1100) 308 | configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:configurationIdentifier]; 309 | #else 310 | configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:configurationIdentifier]; 311 | #endif 312 | } 313 | } 314 | 315 | self = [self initWithBaseURL:baseURL sessionConfiguration:configuration]; 316 | if (!self) { 317 | return nil; 318 | } 319 | 320 | self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))]; 321 | self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))]; 322 | AFSecurityPolicy *decodedPolicy = [decoder decodeObjectOfClass:[AFSecurityPolicy class] forKey:NSStringFromSelector(@selector(securityPolicy))]; 323 | if (decodedPolicy) { 324 | self.securityPolicy = decodedPolicy; 325 | } 326 | 327 | return self; 328 | } 329 | 330 | - (void)encodeWithCoder:(NSCoder *)coder { 331 | [super encodeWithCoder:coder]; 332 | 333 | [coder encodeObject:self.baseURL forKey:NSStringFromSelector(@selector(baseURL))]; 334 | if ([self.session.configuration conformsToProtocol:@protocol(NSCoding)]) { 335 | [coder encodeObject:self.session.configuration forKey:@"sessionConfiguration"]; 336 | } else { 337 | [coder encodeObject:self.session.configuration.identifier forKey:@"identifier"]; 338 | } 339 | [coder encodeObject:self.requestSerializer forKey:NSStringFromSelector(@selector(requestSerializer))]; 340 | [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; 341 | [coder encodeObject:self.securityPolicy forKey:NSStringFromSelector(@selector(securityPolicy))]; 342 | } 343 | 344 | #pragma mark - NSCopying 345 | 346 | - (instancetype)copyWithZone:(NSZone *)zone { 347 | AFHTTPSessionManager *HTTPClient = [[[self class] allocWithZone:zone] initWithBaseURL:self.baseURL sessionConfiguration:self.session.configuration]; 348 | 349 | HTTPClient.requestSerializer = [self.requestSerializer copyWithZone:zone]; 350 | HTTPClient.responseSerializer = [self.responseSerializer copyWithZone:zone]; 351 | HTTPClient.securityPolicy = [self.securityPolicy copyWithZone:zone]; 352 | return HTTPClient; 353 | } 354 | 355 | @end 356 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/MBProgressHUD/MBProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBProgressHUD.h 3 | // Version 0.9.2 4 | // Created by Matej Bukovinski on 2.4.09. 5 | // 6 | 7 | // This code is distributed under the terms and conditions of the MIT license. 8 | 9 | // Copyright (c) 2009-2015 Matej Bukovinski 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | 29 | #import 30 | #import 31 | #import 32 | 33 | @class MBBackgroundView; 34 | @protocol MBProgressHUDDelegate; 35 | 36 | 37 | extern CGFloat const MBProgressMaxOffset; 38 | 39 | typedef NS_ENUM(NSInteger, MBProgressHUDMode) { 40 | /// UIActivityIndicatorView. 41 | MBProgressHUDModeIndeterminate, 42 | /// A round, pie-chart like, progress view. 43 | MBProgressHUDModeDeterminate, 44 | /// Horizontal progress bar. 45 | MBProgressHUDModeDeterminateHorizontalBar, 46 | /// Ring-shaped progress view. 47 | MBProgressHUDModeAnnularDeterminate, 48 | /// Shows a custom view. 49 | MBProgressHUDModeCustomView, 50 | /// Shows only labels. 51 | MBProgressHUDModeText 52 | }; 53 | 54 | typedef NS_ENUM(NSInteger, MBProgressHUDAnimation) { 55 | /// Opacity animation 56 | MBProgressHUDAnimationFade, 57 | /// Opacity + scale animation (zoom in when appearing zoom out when disappearing) 58 | MBProgressHUDAnimationZoom, 59 | /// Opacity + scale animation (zoom out style) 60 | MBProgressHUDAnimationZoomOut, 61 | /// Opacity + scale animation (zoom in style) 62 | MBProgressHUDAnimationZoomIn 63 | }; 64 | 65 | typedef NS_ENUM(NSInteger, MBProgressHUDBackgroundStyle) { 66 | /// Solid color background 67 | MBProgressHUDBackgroundStyleSolidColor, 68 | /// UIVisualEffectView or UIToolbar.layer background view 69 | MBProgressHUDBackgroundStyleBlur 70 | }; 71 | 72 | 73 | NS_ASSUME_NONNULL_BEGIN 74 | 75 | 76 | /** 77 | * Displays a simple HUD window containing a progress indicator and two optional labels for short messages. 78 | * 79 | * This is a simple drop-in class for displaying a progress HUD view similar to Apple's private UIProgressHUD class. 80 | * The MBProgressHUD window spans over the entire space given to it by the initWithFrame: constructor and catches all 81 | * user input on this region, thereby preventing the user operations on components below the view. 82 | * 83 | * @note To still allow touches to pass through the HUD, you can set hud.userInteractionEnabled = NO. 84 | * @attention MBProgressHUD is a UI class and should therefore only be accessed on the main thread. 85 | */ 86 | @interface MBProgressHUD : UIView 87 | 88 | /** 89 | * Creates a new HUD, adds it to provided view and shows it. The counterpart to this method is hideHUDForView:animated:. 90 | * 91 | * @note This method sets removeFromSuperViewOnHide. The HUD will automatically be removed from the view hierarchy when hidden. 92 | * 93 | * @param view The view that the HUD will be added to 94 | * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use 95 | * animations while appearing. 96 | * @return A reference to the created HUD. 97 | * 98 | * @see hideHUDForView:animated: 99 | * @see animationType 100 | */ 101 | + (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated; 102 | 103 | /// @name Showing and hiding 104 | 105 | /** 106 | * Finds the top-most HUD subview and hides it. The counterpart to this method is showHUDAddedTo:animated:. 107 | * 108 | * @note This method sets removeFromSuperViewOnHide. The HUD will automatically be removed from the view hierarchy when hidden. 109 | * 110 | * @param view The view that is going to be searched for a HUD subview. 111 | * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use 112 | * animations while disappearing. 113 | * @return YES if a HUD was found and removed, NO otherwise. 114 | * 115 | * @see showHUDAddedTo:animated: 116 | * @see animationType 117 | */ 118 | + (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated; 119 | 120 | /** 121 | * Finds the top-most HUD subview and returns it. 122 | * 123 | * @param view The view that is going to be searched. 124 | * @return A reference to the last HUD subview discovered. 125 | */ 126 | + (nullable MBProgressHUD *)HUDForView:(UIView *)view; 127 | 128 | /** 129 | * A convenience constructor that initializes the HUD with the view's bounds. Calls the designated constructor with 130 | * view.bounds as the parameter. 131 | * 132 | * @param view The view instance that will provide the bounds for the HUD. Should be the same instance as 133 | * the HUD's superview (i.e., the view that the HUD will be added to). 134 | */ 135 | - (instancetype)initWithView:(UIView *)view; 136 | 137 | /** 138 | * Displays the HUD. 139 | * 140 | * @note You need to make sure that the main thread completes its run loop soon after this method call so that 141 | * the user interface can be updated. Call this method when your task is already set up to be executed in a new thread 142 | * (e.g., when using something like NSOperation or making an asynchronous call like NSURLRequest). 143 | * 144 | * @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use 145 | * animations while appearing. 146 | * 147 | * @see animationType 148 | */ 149 | - (void)showAnimated:(BOOL)animated; 150 | 151 | /** 152 | * Hides the HUD. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to 153 | * hide the HUD when your task completes. 154 | * 155 | * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use 156 | * animations while disappearing. 157 | * 158 | * @see animationType 159 | */ 160 | - (void)hideAnimated:(BOOL)animated; 161 | 162 | /** 163 | * Hides the HUD after a delay. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to 164 | * hide the HUD when your task completes. 165 | * 166 | * @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use 167 | * animations while disappearing. 168 | * @param delay Delay in seconds until the HUD is hidden. 169 | * 170 | * @see animationType 171 | */ 172 | - (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay; 173 | 174 | /** 175 | * The HUD delegate object. Receives HUD state notifications. 176 | */ 177 | @property (weak, nonatomic) id delegate; 178 | 179 | /* 180 | * Grace period is the time (in seconds) that the invoked method may be run without 181 | * showing the HUD. If the task finishes before the grace time runs out, the HUD will 182 | * not be shown at all. 183 | * This may be used to prevent HUD display for very short tasks. 184 | * Defaults to 0 (no grace time). 185 | */ 186 | @property (assign, nonatomic) NSTimeInterval graceTime; 187 | 188 | /** 189 | * The minimum time (in seconds) that the HUD is shown. 190 | * This avoids the problem of the HUD being shown and than instantly hidden. 191 | * Defaults to 0 (no minimum show time). 192 | */ 193 | @property (assign, nonatomic) NSTimeInterval minShowTime; 194 | 195 | /** 196 | * Removes the HUD from its parent view when hidden. 197 | * Defaults to NO. 198 | */ 199 | @property (assign, nonatomic) BOOL removeFromSuperViewOnHide; 200 | 201 | /// @name Appearance 202 | 203 | /** 204 | * MBProgressHUD operation mode. The default is MBProgressHUDModeIndeterminate. 205 | */ 206 | @property (assign, nonatomic) MBProgressHUDMode mode; 207 | 208 | /** 209 | * A color that gets forwarded to all labels and supported indicators. Also sets the tintColor 210 | * for custom views on iOS 7+. Set to nil to manage color individually. 211 | * Defaults to semi-translucent black on iOS 7 and later and white on earlier iOS versions. 212 | */ 213 | @property (strong, nonatomic, nullable) UIColor *contentColor UI_APPEARANCE_SELECTOR; 214 | 215 | /** 216 | * The animation type that should be used when the HUD is shown and hidden. 217 | */ 218 | @property (assign, nonatomic) MBProgressHUDAnimation animationType UI_APPEARANCE_SELECTOR; 219 | 220 | /** 221 | * The bezel offset relative to the center of the view. You can use MBProgressMaxOffset 222 | * and -MBProgressMaxOffset to move the HUD all the way to the screen edge in each direction. 223 | * E.g., CGPointMake(0.f, MBProgressMaxOffset) would position the HUD centered on the bottom edge. 224 | */ 225 | @property (assign, nonatomic) CGPoint offset UI_APPEARANCE_SELECTOR; 226 | 227 | /** 228 | * The amount of space between the HUD edge and the HUD elements (labels, indicators or custom views). 229 | * This also represents the minimum bezel distance to the edge of the HUD view. 230 | * Defaults to 20.f 231 | */ 232 | @property (assign, nonatomic) CGFloat margin UI_APPEARANCE_SELECTOR; 233 | 234 | /** 235 | * The minimum size of the HUD bezel. Defaults to CGSizeZero (no minimum size). 236 | */ 237 | @property (assign, nonatomic) CGSize minSize UI_APPEARANCE_SELECTOR; 238 | 239 | /** 240 | * Force the HUD dimensions to be equal if possible. 241 | */ 242 | @property (assign, nonatomic, getter = isSquare) BOOL square UI_APPEARANCE_SELECTOR; 243 | 244 | /** 245 | * When enabled, the bezel center gets slightly affected by the device accelerometer data. 246 | * Has no effect on iOS < 7.0. Defaults to YES. 247 | */ 248 | @property (assign, nonatomic, getter=areDefaultMotionEffectsEnabled) BOOL defaultMotionEffectsEnabled UI_APPEARANCE_SELECTOR; 249 | 250 | /// @name Progress 251 | 252 | /** 253 | * The progress of the progress indicator, from 0.0 to 1.0. Defaults to 0.0. 254 | */ 255 | @property (assign, nonatomic) float progress; 256 | 257 | /// @name Views 258 | 259 | /** 260 | * The view containing the labels and indicator (or customView). 261 | */ 262 | @property (strong, nonatomic, readonly) MBBackgroundView *bezelView; 263 | 264 | /** 265 | * View covering the entire HUD area, placed behind bezelView. 266 | */ 267 | @property (strong, nonatomic, readonly) MBBackgroundView *backgroundView; 268 | 269 | /** 270 | * The UIView (e.g., a UIImageView) to be shown when the HUD is in MBProgressHUDModeCustomView. 271 | * The view should implement intrinsicContentSize for proper sizing. For best results use approximately 37 by 37 pixels. 272 | */ 273 | @property (strong, nonatomic, nullable) UIView *customView; 274 | 275 | /** 276 | * A label that holds an optional short message to be displayed below the activity indicator. The HUD is automatically resized to fit 277 | * the entire text. 278 | */ 279 | @property (strong, nonatomic, readonly) UILabel *label; 280 | 281 | /** 282 | * A label that holds an optional details message displayed below the labelText message. The details text can span multiple lines. 283 | */ 284 | @property (strong, nonatomic, readonly) UILabel *detailsLabel; 285 | 286 | /** 287 | * A button that is placed below the labels. Visible only if a target / action is added. 288 | */ 289 | @property (strong, nonatomic, readonly) UIButton *button; 290 | 291 | @end 292 | 293 | 294 | @protocol MBProgressHUDDelegate 295 | 296 | @optional 297 | 298 | /** 299 | * Called after the HUD was fully hidden from the screen. 300 | */ 301 | - (void)hudWasHidden:(MBProgressHUD *)hud; 302 | 303 | @end 304 | 305 | 306 | /** 307 | * A progress view for showing definite progress by filling up a circle (pie chart). 308 | */ 309 | @interface MBRoundProgressView : UIView 310 | 311 | /** 312 | * Progress (0.0 to 1.0) 313 | */ 314 | @property (nonatomic, assign) float progress; 315 | 316 | /** 317 | * Indicator progress color. 318 | * Defaults to white [UIColor whiteColor]. 319 | */ 320 | @property (nonatomic, strong) UIColor *progressTintColor; 321 | 322 | /** 323 | * Indicator background (non-progress) color. 324 | * Only applicable on iOS versions older than iOS 7. 325 | * Defaults to translucent white (alpha 0.1). 326 | */ 327 | @property (nonatomic, strong) UIColor *backgroundTintColor; 328 | 329 | /* 330 | * Display mode - NO = round or YES = annular. Defaults to round. 331 | */ 332 | @property (nonatomic, assign, getter = isAnnular) BOOL annular; 333 | 334 | @end 335 | 336 | 337 | /** 338 | * A flat bar progress view. 339 | */ 340 | @interface MBBarProgressView : UIView 341 | 342 | /** 343 | * Progress (0.0 to 1.0) 344 | */ 345 | @property (nonatomic, assign) float progress; 346 | 347 | /** 348 | * Bar border line color. 349 | * Defaults to white [UIColor whiteColor]. 350 | */ 351 | @property (nonatomic, strong) UIColor *lineColor; 352 | 353 | /** 354 | * Bar background color. 355 | * Defaults to clear [UIColor clearColor]; 356 | */ 357 | @property (nonatomic, strong) UIColor *progressRemainingColor; 358 | 359 | /** 360 | * Bar progress color. 361 | * Defaults to white [UIColor whiteColor]. 362 | */ 363 | @property (nonatomic, strong) UIColor *progressColor; 364 | 365 | @end 366 | 367 | 368 | @interface MBBackgroundView : UIView 369 | 370 | /** 371 | * The background style. 372 | * Defaults to MBProgressHUDBackgroundStyleBlur on iOS 7 or later and MBProgressHUDBackgroundStyleSolidColor otherwise. 373 | * @note Due to iOS 7 not supporting UIVisualEffectView, the blur effect differs slightly between iOS 7 and later versions. 374 | */ 375 | @property (nonatomic) MBProgressHUDBackgroundStyle style; 376 | 377 | /** 378 | * The background color or the blur tint color. 379 | * @note Due to iOS 7 not supporting UIVisualEffectView, the blur effect differs slightly between iOS 7 and later versions. 380 | */ 381 | @property (nonatomic, strong) UIColor *color; 382 | 383 | @end 384 | 385 | @interface MBProgressHUD (Deprecated) 386 | 387 | + (NSArray *)allHUDsForView:(UIView *)view __attribute__((deprecated("Store references when using more than one HUD per view."))); 388 | + (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated __attribute__((deprecated("Store references when using more than one HUD per view."))); 389 | 390 | - (id)initWithWindow:(UIWindow *)window __attribute__((deprecated("Use initWithView: instead."))); 391 | 392 | - (void)show:(BOOL)animated __attribute__((deprecated("Use showAnimated: instead."))); 393 | - (void)hide:(BOOL)animated __attribute__((deprecated("Use hideAnimated: instead."))); 394 | - (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay __attribute__((deprecated("Use hideAnimated:afterDelay: instead."))); 395 | 396 | typedef void (^MBProgressHUDCompletionBlock)(); 397 | 398 | - (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated __attribute__((deprecated("Use GCD directly."))); 399 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block __attribute__((deprecated("Use GCD directly."))); 400 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(nullable MBProgressHUDCompletionBlock)completion __attribute__((deprecated("Use GCD directly."))); 401 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue __attribute__((deprecated("Use GCD directly."))); 402 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue 403 | completionBlock:(nullable MBProgressHUDCompletionBlock)completion __attribute__((deprecated("Use GCD directly."))); 404 | @property (copy, nullable) MBProgressHUDCompletionBlock completionBlock __attribute__((deprecated("Use GCD directly."))); 405 | @property (assign) BOOL taskInProgress __attribute__((deprecated("No longer needed."))); 406 | 407 | @property (nonatomic, copy) NSString *labelText __attribute__((deprecated("Use label.text instead."))); 408 | @property (nonatomic, strong) UIFont *labelFont __attribute__((deprecated("Use label.font instead."))); 409 | @property (nonatomic, strong) UIColor *labelColor __attribute__((deprecated("Use label.textColor instead."))); 410 | @property (nonatomic, copy) NSString *detailsLabelText __attribute__((deprecated("Use detailsLabel.text instead."))); 411 | @property (nonatomic, strong) UIFont *detailsLabelFont __attribute__((deprecated("Use detailsLabel.font instead."))); 412 | @property (nonatomic, strong) UIColor *detailsLabelColor __attribute__((deprecated("Use detailsLabel.textColor instead."))); 413 | @property (assign, nonatomic) CGFloat opacity __attribute__((deprecated("Customize bezelView properties instead."))); 414 | @property (strong, nonatomic) UIColor *color __attribute__((deprecated("Customize the bezelView color instead."))); 415 | @property (assign, nonatomic) CGFloat xOffset __attribute__((deprecated("Set offset.x instead."))); 416 | @property (assign, nonatomic) CGFloat yOffset __attribute__((deprecated("Set offset.y instead."))); 417 | @property (assign, nonatomic) CGFloat cornerRadius __attribute__((deprecated("Set bezelView.layer.cornerRadius instead."))); 418 | @property (assign, nonatomic) BOOL dimBackground __attribute__((deprecated("Customize HUD background properties instead."))); 419 | @property (strong, nonatomic) UIColor *activityIndicatorColor __attribute__((deprecated("Use UIAppearance to customize UIActivityIndicatorView."))); 420 | @property (atomic, assign, readonly) CGSize size __attribute__((deprecated("Get the bezelView.frame.size instead."))); 421 | 422 | @end 423 | 424 | NS_ASSUME_NONNULL_END 425 | -------------------------------------------------------------------------------- /TYHttpManagerDemo/AFNetworking/AFHTTPSessionManager.h: -------------------------------------------------------------------------------- 1 | // AFHTTPSessionManager.h 2 | // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | #import 23 | #if !TARGET_OS_WATCH 24 | #import 25 | #endif 26 | #import 27 | 28 | #if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_TV 29 | #import 30 | #else 31 | #import 32 | #endif 33 | 34 | #import "AFURLSessionManager.h" 35 | 36 | /** 37 | `AFHTTPSessionManager` is a subclass of `AFURLSessionManager` with convenience methods for making HTTP requests. When a `baseURL` is provided, requests made with the `GET` / `POST` / et al. convenience methods can be made with relative paths. 38 | 39 | ## Subclassing Notes 40 | 41 | Developers targeting iOS 7 or Mac OS X 10.9 or later that deal extensively with a web service are encouraged to subclass `AFHTTPSessionManager`, providing a class method that returns a shared singleton object on which authentication and other configuration can be shared across the application. 42 | 43 | For developers targeting iOS 6 or Mac OS X 10.8 or earlier, `AFHTTPRequestOperationManager` may be used to similar effect. 44 | 45 | ## Methods to Override 46 | 47 | To change the behavior of all data task operation construction, which is also used in the `GET` / `POST` / et al. convenience methods, override `dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:`. 48 | 49 | ## Serialization 50 | 51 | Requests created by an HTTP client will contain default headers and encode parameters according to the `requestSerializer` property, which is an object conforming to ``. 52 | 53 | Responses received from the server are automatically validated and serialized by the `responseSerializers` property, which is an object conforming to `` 54 | 55 | ## URL Construction Using Relative Paths 56 | 57 | For HTTP convenience methods, the request serializer constructs URLs from the path relative to the `-baseURL`, using `NSURL +URLWithString:relativeToURL:`, when provided. If `baseURL` is `nil`, `path` needs to resolve to a valid `NSURL` object using `NSURL +URLWithString:`. 58 | 59 | Below are a few examples of how `baseURL` and relative paths interact: 60 | 61 | NSURL *baseURL = [NSURL URLWithString:@"http://example.com/v1/"]; 62 | [NSURL URLWithString:@"foo" relativeToURL:baseURL]; // http://example.com/v1/foo 63 | [NSURL URLWithString:@"foo?bar=baz" relativeToURL:baseURL]; // http://example.com/v1/foo?bar=baz 64 | [NSURL URLWithString:@"/foo" relativeToURL:baseURL]; // http://example.com/foo 65 | [NSURL URLWithString:@"foo/" relativeToURL:baseURL]; // http://example.com/v1/foo 66 | [NSURL URLWithString:@"/foo/" relativeToURL:baseURL]; // http://example.com/foo/ 67 | [NSURL URLWithString:@"http://example2.com/" relativeToURL:baseURL]; // http://example2.com/ 68 | 69 | Also important to note is that a trailing slash will be added to any `baseURL` without one. This would otherwise cause unexpected behavior when constructing URLs using paths without a leading slash. 70 | 71 | @warning Managers for background sessions must be owned for the duration of their use. This can be accomplished by creating an application-wide or shared singleton instance. 72 | */ 73 | 74 | NS_ASSUME_NONNULL_BEGIN 75 | 76 | @interface AFHTTPSessionManager : AFURLSessionManager 77 | 78 | /** 79 | The URL used to construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods. 80 | */ 81 | @property (readonly, nonatomic, strong, nullable) NSURL *baseURL; 82 | 83 | /** 84 | Requests created with `requestWithMethod:URLString:parameters:` & `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:` are constructed with a set of default headers using a parameter serialization specified by this property. By default, this is set to an instance of `AFHTTPRequestSerializer`, which serializes query string parameters for `GET`, `HEAD`, and `DELETE` requests, or otherwise URL-form-encodes HTTP message bodies. 85 | 86 | @warning `requestSerializer` must not be `nil`. 87 | */ 88 | @property (nonatomic, strong) AFHTTPRequestSerializer * requestSerializer; 89 | 90 | /** 91 | Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an instance of `AFJSONResponseSerializer`. 92 | 93 | @warning `responseSerializer` must not be `nil`. 94 | */ 95 | @property (nonatomic, strong) AFHTTPResponseSerializer * responseSerializer; 96 | 97 | ///--------------------- 98 | /// @name Initialization 99 | ///--------------------- 100 | 101 | /** 102 | Creates and returns an `AFHTTPSessionManager` object. 103 | */ 104 | + (instancetype)manager; 105 | 106 | /** 107 | Initializes an `AFHTTPSessionManager` object with the specified base URL. 108 | 109 | @param url The base URL for the HTTP client. 110 | 111 | @return The newly-initialized HTTP client 112 | */ 113 | - (instancetype)initWithBaseURL:(nullable NSURL *)url; 114 | 115 | /** 116 | Initializes an `AFHTTPSessionManager` object with the specified base URL. 117 | 118 | This is the designated initializer. 119 | 120 | @param url The base URL for the HTTP client. 121 | @param configuration The configuration used to create the managed session. 122 | 123 | @return The newly-initialized HTTP client 124 | */ 125 | - (instancetype)initWithBaseURL:(nullable NSURL *)url 126 | sessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER; 127 | 128 | ///--------------------------- 129 | /// @name Making HTTP Requests 130 | ///--------------------------- 131 | 132 | /** 133 | Creates and runs an `NSURLSessionDataTask` with a `GET` request. 134 | 135 | @param URLString The URL string used to create the request URL. 136 | @param parameters The parameters to be encoded according to the client request serializer. 137 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 138 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 139 | 140 | @see -dataTaskWithRequest:completionHandler: 141 | */ 142 | - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString 143 | parameters:(nullable id)parameters 144 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 145 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE; 146 | 147 | 148 | /** 149 | Creates and runs an `NSURLSessionDataTask` with a `GET` request. 150 | 151 | @param URLString The URL string used to create the request URL. 152 | @param parameters The parameters to be encoded according to the client request serializer. 153 | @param downloadProgress A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue. 154 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 155 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 156 | 157 | @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler: 158 | */ 159 | - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString 160 | parameters:(nullable id)parameters 161 | progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress 162 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 163 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; 164 | 165 | /** 166 | Creates and runs an `NSURLSessionDataTask` with a `HEAD` request. 167 | 168 | @param URLString The URL string used to create the request URL. 169 | @param parameters The parameters to be encoded according to the client request serializer. 170 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes a single arguments: the data task. 171 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 172 | 173 | @see -dataTaskWithRequest:completionHandler: 174 | */ 175 | - (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString 176 | parameters:(nullable id)parameters 177 | success:(nullable void (^)(NSURLSessionDataTask *task))success 178 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; 179 | 180 | /** 181 | Creates and runs an `NSURLSessionDataTask` with a `POST` request. 182 | 183 | @param URLString The URL string used to create the request URL. 184 | @param parameters The parameters to be encoded according to the client request serializer. 185 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 186 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 187 | 188 | @see -dataTaskWithRequest:completionHandler: 189 | */ 190 | - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString 191 | parameters:(nullable id)parameters 192 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 193 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE; 194 | 195 | /** 196 | Creates and runs an `NSURLSessionDataTask` with a `POST` request. 197 | 198 | @param URLString The URL string used to create the request URL. 199 | @param parameters The parameters to be encoded according to the client request serializer. 200 | @param uploadProgress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue. 201 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 202 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 203 | 204 | @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler: 205 | */ 206 | - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString 207 | parameters:(nullable id)parameters 208 | progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress 209 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 210 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; 211 | 212 | /** 213 | Creates and runs an `NSURLSessionDataTask` with a multipart `POST` request. 214 | 215 | @param URLString The URL string used to create the request URL. 216 | @param parameters The parameters to be encoded according to the client request serializer. 217 | @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol. 218 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 219 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 220 | 221 | @see -dataTaskWithRequest:completionHandler: 222 | */ 223 | - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString 224 | parameters:(nullable id)parameters 225 | constructingBodyWithBlock:(nullable void (^)(id formData))block 226 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 227 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE; 228 | 229 | /** 230 | Creates and runs an `NSURLSessionDataTask` with a multipart `POST` request. 231 | 232 | @param URLString The URL string used to create the request URL. 233 | @param parameters The parameters to be encoded according to the client request serializer. 234 | @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol. 235 | @param uploadProgress A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue. 236 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 237 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 238 | 239 | @see -dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler: 240 | */ 241 | - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString 242 | parameters:(nullable id)parameters 243 | constructingBodyWithBlock:(nullable void (^)(id formData))block 244 | progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress 245 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 246 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; 247 | 248 | /** 249 | Creates and runs an `NSURLSessionDataTask` with a `PUT` request. 250 | 251 | @param URLString The URL string used to create the request URL. 252 | @param parameters The parameters to be encoded according to the client request serializer. 253 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 254 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 255 | 256 | @see -dataTaskWithRequest:completionHandler: 257 | */ 258 | - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString 259 | parameters:(nullable id)parameters 260 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 261 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; 262 | 263 | /** 264 | Creates and runs an `NSURLSessionDataTask` with a `PATCH` request. 265 | 266 | @param URLString The URL string used to create the request URL. 267 | @param parameters The parameters to be encoded according to the client request serializer. 268 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 269 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 270 | 271 | @see -dataTaskWithRequest:completionHandler: 272 | */ 273 | - (nullable NSURLSessionDataTask *)PATCH:(NSString *)URLString 274 | parameters:(nullable id)parameters 275 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 276 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; 277 | 278 | /** 279 | Creates and runs an `NSURLSessionDataTask` with a `DELETE` request. 280 | 281 | @param URLString The URL string used to create the request URL. 282 | @param parameters The parameters to be encoded according to the client request serializer. 283 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 284 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 285 | 286 | @see -dataTaskWithRequest:completionHandler: 287 | */ 288 | - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString 289 | parameters:(nullable id)parameters 290 | success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success 291 | failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; 292 | 293 | @end 294 | 295 | NS_ASSUME_NONNULL_END 296 | --------------------------------------------------------------------------------