├── .gitignore ├── AJNetworking.podspec ├── AJNetworking.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── AJNetworking.xcworkspace └── contents.xcworkspacedata ├── AJNetworking ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── testImg.imageset │ │ ├── Contents.json │ │ └── testImg@2x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Classes │ ├── AJCacheOptions.h │ ├── AJCacheOptions.m │ ├── AJError.h │ ├── AJError.m │ ├── AJHubProtocol.h │ ├── AJNetworkConfig.h │ ├── AJNetworkConfig.m │ ├── AJNetworkLog.h │ ├── AJNetworkLog.m │ ├── AJNetworkManager.h │ ├── AJNetworkManager.m │ ├── AJNetworkStatus.h │ ├── AJNetworkStatus.m │ ├── AJNetworking.h │ ├── Model │ │ ├── AJRequestBeanBase.h │ │ ├── AJRequestBeanBase.m │ │ ├── AJRequestBeanDownloadTaskBase.h │ │ ├── AJRequestBeanDownloadTaskBase.m │ │ ├── AJRequestBeanProtocol.h │ │ ├── AJResponseBeanBase.h │ │ ├── AJResponseBeanBase.m │ │ └── AJResponseBeanProtocol.h │ └── Utils │ │ ├── MD5Util.h │ │ └── MD5Util.m ├── Demo │ ├── BViewController.h │ ├── BViewController.m │ ├── RequestBeanDemoBase.h │ ├── RequestBeanDemoBase.m │ ├── RequestBeanDemoFilm.h │ ├── RequestBeanDemoFilm.m │ ├── RequestBeanDemoLogin.h │ ├── RequestBeanDemoLogin.m │ ├── RequestBeanDemoNews.h │ ├── RequestBeanDemoNews.m │ ├── RequestBeanDemoRegister.h │ ├── RequestBeanDemoRegister.m │ ├── RequestBeanVersion.h │ ├── RequestBeanVersion.m │ ├── RequestConfig.h │ ├── RequestConfig.m │ ├── RequestConfig.plist │ ├── ResponseBeanDemo.h │ ├── ResponseBeanDemo.m │ ├── ResponseBeanDemoFilm.h │ ├── ResponseBeanDemoFilm.m │ ├── ResponseBeanDemoLogin.h │ ├── ResponseBeanDemoLogin.m │ ├── ResponseBeanDemoNews.h │ ├── ResponseBeanDemoNews.m │ ├── ResponseBeanDemoRegister.h │ ├── ResponseBeanDemoRegister.m │ ├── User.h │ ├── User.m │ ├── ViewController.h │ └── ViewController.m ├── Example │ ├── Certificate │ │ └── client_test_local.p12 │ ├── LoginViewController.h │ ├── LoginViewController.m │ ├── Model │ │ ├── AlipayConfigBean.h │ │ ├── AlipayConfigBean.m │ │ ├── CompanyBean.h │ │ ├── CompanyBean.m │ │ ├── RequestBeanAlipayConfig.h │ │ ├── RequestBeanAlipayConfig.m │ │ ├── RequestBeanDownloadFile.h │ │ ├── RequestBeanDownloadFile.m │ │ ├── RequestBeanLogin.h │ │ ├── RequestBeanLogin.m │ │ ├── RequestBeanUploadAvatar.h │ │ ├── RequestBeanUploadAvatar.m │ │ ├── ResponseBeanAlipayConfig.h │ │ ├── ResponseBeanAlipayConfig.m │ │ ├── ResponseBeanDownloadFile.h │ │ ├── ResponseBeanDownloadFile.m │ │ ├── ResponseBeanExample.h │ │ ├── ResponseBeanExample.m │ │ ├── ResponseBeanLogin.h │ │ ├── ResponseBeanLogin.m │ │ ├── ResponseBeanUploadAvatar.h │ │ └── ResponseBeanUploadAvatar.m │ └── Utils │ │ ├── Base64 │ │ ├── Base64.h │ │ └── Base64.m │ │ ├── NSData+Base64.h │ │ ├── NSData+Base64.m │ │ ├── TripleDESEncrypt.h │ │ └── TripleDESEncrypt.m ├── Info.plist ├── NetworkHub.h ├── NetworkHub.m ├── client.p12 └── main.m ├── LICENSE ├── Podfile ├── Podfile.lock ├── README.md └── StructureFlow.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | -------------------------------------------------------------------------------- /AJNetworking.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | 4 | s.name = "AJNetworking" 5 | s.version = "3.2.0" 6 | s.summary = "AJNetworking是对AFNetworking 3.x 版本的封装,内部集成缓存和JSON转化." 7 | 8 | s.description = <<-DESC 9 | AJNetworking是对网络层的封装,将网络请求、JSON数据转化和数据缓存合三为一,上层可以更专注于业务的处理。 10 | DESC 11 | 12 | s.homepage = "https://github.com/AbooJan/AJNetworking" 13 | 14 | s.license = "MIT" 15 | s.license = { :type => "MIT", :file => "LICENSE" } 16 | s.author = { "AbooJan" => "aboojaner@gmail.com" } 17 | 18 | s.platform = :ios 19 | s.platform = :ios, "7.0" 20 | s.ios.deployment_target = "7.0" 21 | 22 | s.source = { :git => "https://github.com/AbooJan/AJNetworking.git", :tag => "#{s.version}" } 23 | s.source_files = "AJNetworking/Classes/*.{h,m}","AJNetworking/Classes/Model/*.{h,m}","AJNetworking/Classes/Utils/*.{h,m}" 24 | 25 | s.frameworks = "UIKit","Foundation","Security" 26 | s.requires_arc = true 27 | 28 | s.dependency "AFNetworking" 29 | s.dependency "MJExtension" 30 | s.dependency "SPTPersistentCache" 31 | 32 | end 33 | -------------------------------------------------------------------------------- /AJNetworking.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AJNetworking.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AJNetworking/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/3/19. 6 | // Copyright © 2016年 aboojan. 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 | -------------------------------------------------------------------------------- /AJNetworking/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/3/19. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "AJNetworking.h" 11 | #import "NetworkHub.h" 12 | 13 | @interface AppDelegate () 14 | @property (nonatomic, strong) NetworkHub *hub; 15 | @end 16 | 17 | @implementation AppDelegate 18 | 19 | 20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 21 | 22 | NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; 23 | AJLog(@"%@", documentsPath); 24 | 25 | self.hub = [[NetworkHub alloc] init]; 26 | 27 | // 网络配置 28 | AJNetworkConfig *networkConfig = [AJNetworkConfig shareInstance]; 29 | networkConfig.hostUrl = @"localhost:3000"; 30 | // networkConfig.hostUrl = @"192.168.1.10:80"; 31 | networkConfig.httpsCertificatePassword = CFSTR("666666"); 32 | networkConfig.httpsCertificatePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"]; 33 | networkConfig.hubDelegate = self.hub; 34 | 35 | // 网络缓存配置 36 | AJCacheOptions *cacheOptions = [AJCacheOptions new]; 37 | cacheOptions.cachePath = [documentsPath stringByAppendingPathComponent:@"aj_network_cache"]; 38 | cacheOptions.openCacheGC = YES; 39 | cacheOptions.globalCacheExpirationSecond = 60; 40 | cacheOptions.globalCacheGCSecond = 2 * 60; 41 | networkConfig.cacheOptions = cacheOptions; 42 | 43 | return YES; 44 | } 45 | 46 | - (void)applicationWillResignActive:(UIApplication *)application { 47 | // 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. 48 | // 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. 49 | } 50 | 51 | - (void)applicationDidEnterBackground:(UIApplication *)application { 52 | // 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. 53 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 54 | } 55 | 56 | - (void)applicationWillEnterForeground:(UIApplication *)application { 57 | // 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. 58 | } 59 | 60 | - (void)applicationDidBecomeActive:(UIApplication *)application { 61 | // 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. 62 | } 63 | 64 | - (void)applicationWillTerminate:(UIApplication *)application { 65 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /AJNetworking/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 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /AJNetworking/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /AJNetworking/Assets.xcassets/testImg.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "testImg@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /AJNetworking/Assets.xcassets/testImg.imageset/testImg@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbooJan/AJNetworking/cb06bcd954c40a84c40ef7e99eb1443fef5eb55b/AJNetworking/Assets.xcassets/testImg.imageset/testImg@2x.png -------------------------------------------------------------------------------- /AJNetworking/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 | -------------------------------------------------------------------------------- /AJNetworking/Base.lproj/Main.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 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 100 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 137 | 144 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 238 | 250 | 262 | 274 | 286 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJCacheOptions.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJCacheOptions.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/4/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | extern const NSUInteger AJCacheDefaultExpirationSecond; 13 | extern const NSUInteger AJCacheDefaultGCSecond; 14 | 15 | 16 | @interface AJCacheOptions : NSObject 17 | 18 | /** 19 | * @author aboojan 20 | * 21 | * @brief 缓存存放路径 22 | */ 23 | @property (nonatomic, copy) NSString *cachePath; 24 | 25 | /** 26 | * @author aboojan 27 | * 28 | * @brief 是否开启缓存自动回收,默认关闭 29 | */ 30 | @property (nonatomic,assign) BOOL openCacheGC; 31 | 32 | /** 33 | * @author aboojan 34 | * 35 | * @brief 缓存过期时间,最小不能小于60s 36 | */ 37 | @property (nonatomic, assign) NSUInteger globalCacheExpirationSecond; 38 | 39 | /** 40 | * @author aboojan 41 | * 42 | * @brief 缓存自动回收时间,最小不能小于60s(开启自动回收之后才有效) 43 | */ 44 | @property (nonatomic, assign) NSUInteger globalCacheGCSecond; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJCacheOptions.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJCacheOptions.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/4/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJCacheOptions.h" 10 | 11 | 12 | const NSUInteger AJCacheDefaultExpirationSecond = 10 * 60; 13 | const NSUInteger AJCacheDefaultGCSecond = 6 * 60 + 3; 14 | 15 | 16 | @implementation AJCacheOptions 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJError.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJError.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/24. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, AJErrorCode) 12 | { 13 | AJErrorCodeDefault = 0, 14 | AJErrorCodeNoCache = 101, 15 | AJErrorCodeCacheInvalid = 102, 16 | AJErrorCodeNoNetwork = 103, 17 | AJErrorCodeNoResponse = 104 18 | }; 19 | 20 | @interface AJError : NSObject 21 | 22 | @property (nonatomic,assign) NSInteger code; 23 | @property (copy, nonatomic) NSString *message; 24 | 25 | + (AJError *)defaultError; 26 | - (instancetype)initWithCode:(NSInteger)code message:(NSString *)message; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJError.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJError.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/24. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJError.h" 10 | 11 | @implementation AJError 12 | 13 | + (AJError *)defaultError 14 | { 15 | AJError *err = [[AJError alloc] initWithCode:AJErrorCodeDefault message:@"error"]; 16 | return err; 17 | } 18 | 19 | - (instancetype)initWithCode:(NSInteger)code message:(NSString *)message 20 | { 21 | self = [super init]; 22 | if (self) { 23 | self.code = code; 24 | self.message = message; 25 | } 26 | return self; 27 | } 28 | 29 | - (NSString *)description 30 | { 31 | return [NSString stringWithFormat:@"code:%ld \n message:%@", self.code, self.message]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJHubProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJHubProtocol.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 2016/9/24. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol AJHubProtocol 12 | 13 | /** 14 | * 显示Hub 15 | * 16 | @param tip hub文案 17 | */ 18 | - (void)showHub:(nullable NSString *)tip; 19 | 20 | 21 | /** 22 | * 隐藏Hub 23 | */ 24 | - (void)dismissHub; 25 | @end 26 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJNetworkConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJNetworkConfig.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/18. 6 | // Copyright © 2016年 Joiway. All rights reserved. 7 | // 8 | 9 | #import "AJCacheOptions.h" 10 | #import 11 | #import 12 | #import "AJHubProtocol.h" 13 | 14 | #ifdef DEBUG 15 | # define AJLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); 16 | #else 17 | # define AJLog(...) 18 | #endif 19 | 20 | #define AJConstructingBlockDefine ^(id formData) 21 | 22 | typedef void (^AFConstructingBlock)(id formData); 23 | 24 | typedef NS_ENUM(NSInteger, HTTP_REQUEST_SERIALIZATION) 25 | { 26 | /// Content-Type:application/x-www-form-urlencoded 27 | HTTP_REQUEST_SERIALIZATION_FORM, 28 | /// Content-Type:application/json 29 | HTTP_REQUEST_SERIALIZATION_JSON, 30 | /// Content-Type:application/x-plist 31 | HTTP_REQUEST_SERIALIZATION_PROPERTY_LIST 32 | }; 33 | 34 | typedef NS_ENUM(NSInteger, HTTP_METHOD) 35 | { 36 | HTTP_METHOD_GET, 37 | HTTP_METHOD_POST, 38 | HTTP_METHOD_HEAD, 39 | HTTP_METHOD_PUT, 40 | HTTP_METHOD_DELETE, 41 | HTTP_METHOD_PATCH 42 | }; 43 | 44 | typedef NS_ENUM(NSInteger, HTTP_SCHEME) 45 | { 46 | HTTP_SCHEME_HTTP, 47 | HTTP_SCHEME_HTTPS 48 | }; 49 | 50 | @interface AJNetworkConfig : NSObject 51 | 52 | + (AJNetworkConfig *)shareInstance; 53 | 54 | - (SPTPersistentCache *)globalHttpCache; 55 | 56 | /// 服务器域名 57 | @property (nonatomic, copy) NSString *hostUrl; 58 | /// HTTPS 证书密码 59 | @property (nonatomic, assign) CFStringRef httpsCertificatePassword; 60 | /// HTTPS 证书路径 61 | @property (nonatomic, copy) NSString *httpsCertificatePath; 62 | /// 缓存配置 63 | @property (nonatomic, strong) AJCacheOptions *cacheOptions; 64 | /// Hub显示代理 65 | @property (nonatomic, weak) id hubDelegate; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJNetworkConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJNetworkConfig.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/18. 6 | // Copyright © 2016年 Joiway. All rights reserved. 7 | // 8 | 9 | #import "AJNetworkConfig.h" 10 | #import "AJNetworkStatus.h" 11 | 12 | #define kBundleID [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"] 13 | 14 | 15 | @interface AJNetworkConfig () 16 | /// 网络缓存 17 | @property (nonatomic, strong) SPTPersistentCache *httpCache; 18 | @end 19 | 20 | @implementation AJNetworkConfig 21 | 22 | + (AJNetworkConfig *)shareInstance 23 | { 24 | static AJNetworkConfig * instance; 25 | static dispatch_once_t onceToken; 26 | dispatch_once(&onceToken, ^{ 27 | instance = [[AJNetworkConfig alloc] init]; 28 | 29 | // 开启网络状态监听 30 | [AJNetworkStatus shareInstance]; 31 | }); 32 | 33 | return instance; 34 | } 35 | 36 | - (SPTPersistentCache *)globalHttpCache 37 | { 38 | if (!_httpCache) { 39 | 40 | NSString *cacheIdentifier = [NSString stringWithFormat:@"%@.cache", kBundleID]; 41 | 42 | // 缓存配置 43 | SPTPersistentCacheOptions *options = [[SPTPersistentCacheOptions alloc] 44 | initWithCachePath:self.cacheOptions.cachePath 45 | identifier:cacheIdentifier 46 | defaultExpirationInterval:self.cacheOptions.globalCacheExpirationSecond 47 | garbageCollectorInterval:self.cacheOptions.globalCacheGCSecond 48 | debug:^(NSString * _Nonnull string) { 49 | 50 | AJLog(@"###SPTPersistentCache###: %@", string); 51 | }]; 52 | 53 | _httpCache = [[SPTPersistentCache alloc] initWithOptions:options]; 54 | 55 | // 开启缓存自动回收 56 | if (self.cacheOptions.openCacheGC) { 57 | [_httpCache scheduleGarbageCollector]; 58 | } 59 | 60 | } 61 | 62 | return _httpCache; 63 | } 64 | 65 | - (AJCacheOptions *)cacheOptions 66 | { 67 | if (!_cacheOptions){ 68 | 69 | _cacheOptions = [[AJCacheOptions alloc] init]; 70 | 71 | _cacheOptions.cachePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@", kBundleID]]; 72 | _cacheOptions.globalCacheExpirationSecond = AJCacheDefaultExpirationSecond; 73 | _cacheOptions.globalCacheGCSecond = AJCacheDefaultGCSecond; 74 | } 75 | 76 | if( (_cacheOptions.cachePath == nil) || [_cacheOptions.cachePath isEqualToString:@""] ) 77 | { 78 | _cacheOptions.cachePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@", kBundleID]]; 79 | } 80 | 81 | if (_cacheOptions.globalCacheExpirationSecond < 60) { 82 | _cacheOptions.globalCacheExpirationSecond = AJCacheDefaultExpirationSecond; 83 | } 84 | 85 | if (_cacheOptions.globalCacheGCSecond < 60) { 86 | _cacheOptions.globalCacheGCSecond = AJCacheDefaultGCSecond; 87 | } 88 | 89 | return _cacheOptions; 90 | } 91 | 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJNetworkLog.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJNetworkLog.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AJRequestBeanBase.h" 11 | #import "AJResponseBeanBase.h" 12 | 13 | @interface AJNetworkLog : NSObject 14 | + (void)logWithRequestBean:(__kindof AJRequestBeanBase *)requestBean; 15 | + (void)logWithRequestBean:(__kindof AJRequestBeanBase *)requestBean json:(id)responseJSON; 16 | + (void)logWithContent:(NSString *)logContent; 17 | @end 18 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJNetworkLog.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJNetworkLog.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJNetworkLog.h" 10 | #import "MJExtension.h" 11 | 12 | 13 | @implementation AJNetworkLog 14 | 15 | + (NSString *)createPostURL:(NSDictionary *)params 16 | { 17 | NSString *postString = @""; 18 | for (NSString *key in params.allKeys) { 19 | NSString *value = [params objectForKey:key]; 20 | postString = [postString stringByAppendingFormat:@"%@=%@&",key,value]; 21 | } 22 | if ([postString length]>1) { 23 | postString=[postString substringToIndex:[postString length]-1]; 24 | } 25 | return postString; 26 | } 27 | 28 | + (void)logWithRequestBean:(__kindof AJRequestBeanBase *)requestBean 29 | { 30 | NSString *hostStr = [requestBean apiHost]; 31 | NSString *apiStr = [requestBean apiPath]; 32 | 33 | BOOL loseConfigHost = (hostStr == nil) || [hostStr isEqualToString:@""]; 34 | NSCAssert(!loseConfigHost, @"找不到Host!"); 35 | 36 | BOOL loseConfigApi = (apiStr == nil) || [apiStr isEqualToString:@""]; 37 | NSCAssert(!loseConfigApi, @"找不到Api路径!"); 38 | 39 | 40 | NSMutableString *logString = [NSMutableString stringWithString:@"\n\n"]; 41 | [logString appendFormat:@"**************************************************************\n"]; 42 | [logString appendFormat:@"* Request Start *\n"]; 43 | [logString appendFormat:@"**************************************************************\n\n"]; 44 | [logString appendFormat:@"请求:\n%@?%@\n\n", [requestBean requestUrl], [self createPostURL:[requestBean mj_keyValues]]]; 45 | [logString appendFormat:@"%@", [requestBean mj_keyValues]]; 46 | [logString appendFormat:@"\n\n"]; 47 | [logString appendFormat:@"**************************************************************\n"]; 48 | [logString appendFormat:@"* Request End *\n"]; 49 | [logString appendFormat:@"**************************************************************\n\n"]; 50 | 51 | AJLog(@"%@", logString); 52 | } 53 | 54 | + (void)logWithRequestBean:(__kindof AJRequestBeanBase *)requestBean json:(id)responseJSON 55 | { 56 | NSMutableString *logString = [NSMutableString stringWithString:@"\n\n"]; 57 | [logString appendFormat:@"==============================================================\n"]; 58 | [logString appendFormat:@"= API Response =\n"]; 59 | [logString appendFormat:@"==============================================================\n\n"]; 60 | [logString appendFormat:@"URL: %@\n\n", [requestBean requestUrl]]; 61 | [logString appendFormat:@"%@", responseJSON]; 62 | [logString appendFormat:@"\n\n"]; 63 | [logString appendFormat:@"==============================================================\n"]; 64 | [logString appendFormat:@"= Response End =\n"]; 65 | [logString appendFormat:@"==============================================================\n\n\n"]; 66 | 67 | AJLog(@"%@", logString); 68 | } 69 | 70 | + (void)logWithContent:(NSString *)logContent 71 | { 72 | NSMutableString *logStr = [NSMutableString stringWithString:@"\n\n"]; 73 | [logStr appendFormat:@"################################################################\n"]; 74 | [logStr appendFormat:@"# Error #\n"]; 75 | [logStr appendFormat:@"################################################################\n\n"]; 76 | [logStr appendFormat:@"%@\n\n", logContent]; 77 | [logStr appendFormat:@"################################################################\n\n\n"]; 78 | 79 | AJLog(@"%@", logStr); 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJNetworkManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJNetworkManager.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/18. 6 | // Copyright © 2016年 AbooJan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AJNetworkConfig.h" 11 | #import "AJRequestBeanBase.h" 12 | #import "AJResponseBeanBase.h" 13 | #import "AJRequestBeanDownloadTaskBase.h" 14 | #import "AJError.h" 15 | 16 | /** 17 | * @author aboojan 18 | * 19 | * @brief 结果回调 20 | * 21 | * @param responseBean 数据Bean,可能是缓存或网络数据 22 | * @param err 错误,如果为nil,回调成功,否则失败 23 | */ 24 | typedef void(^AJRequestCallBack)(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err); 25 | 26 | typedef void(^AJDownloadProgressCallBack)(int64_t totalUnitCount, int64_t completedUnitCount, double progressRate); 27 | typedef void(^AJDownloadCompletionCallBack)(NSURL * _Nullable filePath, NSError * _Nullable error); 28 | 29 | 30 | @interface AJNetworkManager : NSObject 31 | 32 | /** 33 | * @author aboojan 34 | * 35 | * @brief 发请网络请求,没有缓存 36 | * 37 | * @param requestBean 网络请求参数模型Bean 38 | * @param callBack 网络请求结果回调 39 | */ 40 | + (void)requestWithBean:(__kindof AJRequestBeanBase * _Nonnull)requestBean 41 | callBack:(AJRequestCallBack _Nonnull)callBack; 42 | 43 | /** 44 | * @author aboojan 45 | * 46 | * @brief 发起网络请求,有缓存 47 | * 48 | * @param requestBean 网络请求参数模式Bean 49 | * @param cacheCallBack 缓存读取回调 50 | * @param httpCallBack 网络请求结果回调 51 | */ 52 | + (void)requestWithBean:(__kindof AJRequestBeanBase * _Nonnull)requestBean 53 | cacheCallBack:(AJRequestCallBack _Nonnull)cacheCallBack 54 | httpCallBack:(AJRequestCallBack _Nonnull)httpCallBack; 55 | 56 | 57 | /** 58 | * @author aboojan 59 | * 60 | * @brief 文件下载 61 | * 62 | * @param requestBean 文件下载请求Bean 63 | * @param progressCallBack 下载进度回调 64 | * @param completionCallBack 完成回调 65 | * 66 | * @return 当前下载任务线程 67 | */ 68 | + ( NSURLSessionDownloadTask * _Nullable )downloadTaskWithBean:(__kindof AJRequestBeanDownloadTaskBase * _Nonnull)requestBean progress:(AJDownloadProgressCallBack _Nullable )progressCallBack completion:(AJDownloadCompletionCallBack _Nullable)completionCallBack; 69 | 70 | /** 71 | * @author aboojan 72 | * 73 | * @brief 读取缓存 74 | * 75 | * @param requestBean 请求Bean 76 | * @param callBack 读取缓存回调 77 | */ 78 | + (void)cacheWithRequestWithBean:(__kindof AJRequestBeanBase * _Nonnull)requestBean callBack:(AJRequestCallBack _Nonnull)callBack; 79 | 80 | /** 81 | 根据 taskKey 结束目标网络请求任务 82 | 83 | @param taskKeyArray 任务Key数组 84 | */ 85 | + (void)stopRequestTaskWithTaskKey:(NSArray<__kindof NSString *> * _Nonnull)taskKeyArray; 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJNetworkManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJNetworkManager.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/18. 6 | // Copyright © 2016年 AbooJan. All rights reserved. 7 | // 8 | 9 | #import "AJNetworkManager.h" 10 | #import "MJExtension.h" 11 | #import "AJNetworkLog.h" 12 | #import 13 | #import "MD5Util.h" 14 | #import "AJNetworkStatus.h" 15 | 16 | @interface AJNetworkManager() 17 | @property (nonatomic, strong) NSMutableDictionary<__kindof NSString *, __kindof NSURLSessionTask *> *taskStack; 18 | @end 19 | 20 | @implementation AJNetworkManager 21 | 22 | #pragma mark - <基本信息> 23 | 24 | + (AJNetworkManager *)shareInstance 25 | { 26 | static AJNetworkManager *instance; 27 | static dispatch_once_t onceToken; 28 | dispatch_once(&onceToken, ^{ 29 | instance = [[AJNetworkManager alloc] init]; 30 | instance.taskStack = [NSMutableDictionary dictionary]; 31 | }); 32 | 33 | return instance; 34 | } 35 | 36 | + (AFHTTPSessionManager *)httpsSessionManager { 37 | 38 | AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; 39 | AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy]; 40 | securityPolicy.allowInvalidCertificates = YES; 41 | securityPolicy.validatesDomainName = NO; 42 | manager.securityPolicy = securityPolicy; 43 | 44 | __weak __typeof(&*self) weakSelf = self; 45 | [manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing *credential) { 46 | 47 | __strong __typeof__(weakSelf) strongSelf = weakSelf; 48 | 49 | if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) { 50 | 51 | *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; 52 | return NSURLSessionAuthChallengeUseCredential; 53 | 54 | }else if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate) { 55 | 56 | NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:[AJNetworkConfig shareInstance].httpsCertificatePath]; 57 | CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data; 58 | SecIdentityRef identity = NULL; 59 | [strongSelf extractIdentity :inPKCS12Data :&identity]; 60 | SecCertificateRef certificate = NULL; 61 | SecIdentityCopyCertificate (identity, &certificate); 62 | 63 | *credential = [NSURLCredential credentialWithIdentity:identity certificates:nil persistence:NSURLCredentialPersistencePermanent]; 64 | 65 | return NSURLSessionAuthChallengeUseCredential; 66 | 67 | }else{ 68 | return NSURLSessionAuthChallengeUseCredential; 69 | } 70 | }]; 71 | 72 | return manager; 73 | } 74 | 75 | #pragma mark 设置加密信息 76 | + (OSStatus)extractIdentity:(CFDataRef)inP12Data :(SecIdentityRef*)identity 77 | { 78 | OSStatus securityError = errSecSuccess; 79 | CFStringRef password = [AJNetworkConfig shareInstance].httpsCertificatePassword; 80 | const void *keys[] = { kSecImportExportPassphrase }; 81 | const void *values[] = { password }; 82 | 83 | CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); 84 | CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); 85 | securityError = SecPKCS12Import(inP12Data, options, &items); 86 | 87 | if (securityError == 0) 88 | { 89 | CFDictionaryRef ident = CFArrayGetValueAtIndex(items,0); 90 | const void *tempIdentity = NULL; 91 | tempIdentity = CFDictionaryGetValue(ident, kSecImportItemIdentity); 92 | *identity = (SecIdentityRef)tempIdentity; 93 | } 94 | 95 | if (options) 96 | { 97 | CFRelease(options); 98 | } 99 | 100 | return securityError; 101 | } 102 | 103 | 104 | + (Class)responseClassWithRequestBean:(__kindof AJRequestBeanBase *) requestBean 105 | { 106 | NSString *responseBeanNameStr = [requestBean responseBeanClassName]; 107 | if (!responseBeanNameStr) { 108 | responseBeanNameStr = @"AJResponseBeanBase"; 109 | } 110 | 111 | const char *responseBeanName = [responseBeanNameStr UTF8String]; 112 | 113 | Class responseBeanClass = objc_getClass(responseBeanName); 114 | 115 | NSAssert([responseBeanClass isSubclassOfClass:[AJResponseBeanBase class]], @"Response Bean Class must be subclass of AJResponseBeanBase"); 116 | 117 | return responseBeanClass; 118 | } 119 | 120 | 121 | #pragma mark - <请求处理> 122 | 123 | #pragma mark - private 124 | 125 | + (__kindof AFHTTPRequestSerializer *)requestSerializerWithRequestBean:(__kindof AJRequestBeanBase *)requestBean 126 | { 127 | __kindof AFHTTPRequestSerializer *requestSerializer; 128 | switch ([requestBean requestSerialization]) { 129 | case HTTP_REQUEST_SERIALIZATION_FORM: 130 | requestSerializer = [AFHTTPRequestSerializer serializer]; 131 | break; 132 | 133 | case HTTP_REQUEST_SERIALIZATION_JSON: 134 | requestSerializer = [AFJSONRequestSerializer serializer]; 135 | break; 136 | 137 | case HTTP_REQUEST_SERIALIZATION_PROPERTY_LIST: 138 | requestSerializer = [AFPropertyListRequestSerializer serializer]; 139 | break; 140 | 141 | default: 142 | requestSerializer = [AFHTTPRequestSerializer serializer];; 143 | break; 144 | } 145 | requestSerializer.timeoutInterval = [requestBean timeout]; 146 | 147 | return requestSerializer; 148 | } 149 | 150 | + (void)configHttpHeaderWithRequestBean:(__kindof AJRequestBeanBase *)requestBean requestSerializer:(__kindof AFHTTPRequestSerializer *)requestSerializer 151 | { 152 | NSDictionary *headerFieldValueDictionary = [requestBean httpHeader]; 153 | if (headerFieldValueDictionary != nil) { 154 | for (id httpHeaderField in headerFieldValueDictionary.allKeys) { 155 | id value = headerFieldValueDictionary[httpHeaderField]; 156 | if ([httpHeaderField isKindOfClass:[NSString class]] && [value isKindOfClass:[NSString class]]) { 157 | [requestSerializer setValue:(NSString *)value forHTTPHeaderField:(NSString *)httpHeaderField]; 158 | } else { 159 | AJLog(@"Error, class of key/value in headerFieldValueDictionary should be NSString."); 160 | } 161 | } 162 | } 163 | 164 | } 165 | 166 | #pragma mark - public 167 | 168 | + (void)requestWithBean:(__kindof AJRequestBeanBase *)requestBean callBack:(AJRequestCallBack)callBack 169 | { 170 | // 网络检测 171 | if (![[AJNetworkStatus shareInstance] canReachable]) { 172 | 173 | AJError *err = [[AJError alloc] initWithCode:AJErrorCodeNoNetwork message:@"network can not reach"]; 174 | callBack(nil, err); 175 | 176 | return; 177 | } 178 | 179 | // 检查当前是否已经有请求在跑 180 | NSURLSessionTask *oldTask = [[self shareInstance].taskStack objectForKey:[requestBean taskKey]]; 181 | if (oldTask) { 182 | // 如果已有旧的请求在跑,不进行新的请求 183 | return; 184 | } 185 | 186 | // 发起请求 187 | NSString *requestUrl = [requestBean requestUrl]; 188 | NSDictionary *params = [requestBean mj_keyValues]; 189 | 190 | __kindof AFHTTPRequestSerializer *requestSerializer = [self requestSerializerWithRequestBean:requestBean]; 191 | 192 | // Http Header 193 | [self configHttpHeaderWithRequestBean:requestBean requestSerializer:requestSerializer]; 194 | 195 | // 序列化 196 | AFJSONResponseSerializer *responseSerializer = [AFJSONResponseSerializer serializer]; 197 | responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html", @"text/plain", @"application/msexcel", nil]; 198 | 199 | AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; 200 | if ([requestBean httpScheme] == HTTP_SCHEME_HTTPS) { 201 | manager = [self httpsSessionManager]; 202 | } 203 | manager.requestSerializer = requestSerializer; 204 | manager.responseSerializer = responseSerializer; 205 | 206 | // LOG 207 | [AJNetworkLog logWithRequestBean:requestBean]; 208 | 209 | //Hub 210 | [self showHub:requestBean]; 211 | 212 | NSURLSessionTask *requestTask = nil; 213 | __weak __typeof__(self) weakSelf = self; 214 | 215 | 216 | // Request Success Callback 217 | void(^SuccessBlock)(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) = ^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject){ 218 | __strong __typeof__(weakSelf) strongSelf = weakSelf; 219 | 220 | [strongSelf dismissHub:requestBean]; 221 | [strongSelf handleSuccessWithRequestBean:requestBean response:responseObject callBack:callBack]; 222 | [strongSelf stopRequestTaskWithTaskKey:@[[requestBean taskKey]]]; 223 | }; 224 | 225 | // Request Fail Callback 226 | void (^FailBlock)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) = ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { 227 | __strong __typeof__(weakSelf) strongSelf = weakSelf; 228 | 229 | [strongSelf dismissHub:requestBean]; 230 | [strongSelf handleFailureWithError:error callBack:callBack]; 231 | [strongSelf stopRequestTaskWithTaskKey:@[[requestBean taskKey]]]; 232 | }; 233 | 234 | 235 | switch ([requestBean httpMethod]) { 236 | 237 | case HTTP_METHOD_GET: 238 | { 239 | requestTask = [manager GET:requestUrl parameters:params progress:nil success:SuccessBlock failure:FailBlock]; 240 | break; 241 | } 242 | 243 | case HTTP_METHOD_POST: 244 | { 245 | 246 | if ([requestBean constructingBodyBlock] != nil) { 247 | 248 | // 文件等富文本内容 249 | requestTask = [manager POST:requestUrl parameters:params constructingBodyWithBlock:[requestBean constructingBodyBlock] progress:nil success:SuccessBlock failure:FailBlock]; 250 | 251 | }else{ 252 | 253 | requestTask = [manager POST:requestUrl parameters:params progress:nil success:SuccessBlock failure:FailBlock]; 254 | } 255 | 256 | break; 257 | } 258 | 259 | case HTTP_METHOD_HEAD: 260 | { 261 | requestTask = [manager HEAD:requestUrl parameters:params success:^(NSURLSessionDataTask * _Nonnull task) { 262 | __strong __typeof__(weakSelf) strongSelf = weakSelf; 263 | 264 | [strongSelf dismissHub:requestBean]; 265 | [strongSelf handleSuccessWithRequestBean:requestBean response:task callBack:callBack]; 266 | [strongSelf stopRequestTaskWithTaskKey:@[[requestBean taskKey]]]; 267 | 268 | } failure:FailBlock]; 269 | 270 | break; 271 | } 272 | 273 | case HTTP_METHOD_PUT: 274 | { 275 | requestTask = [manager PUT:requestUrl parameters:params success:SuccessBlock failure:FailBlock]; 276 | 277 | break; 278 | } 279 | 280 | case HTTP_METHOD_PATCH: 281 | { 282 | requestTask = [manager PATCH:requestUrl parameters:params success:SuccessBlock failure:FailBlock]; 283 | 284 | break; 285 | } 286 | 287 | case HTTP_METHOD_DELETE: 288 | { 289 | requestTask = [manager DELETE:requestUrl parameters:params success:SuccessBlock failure:FailBlock]; 290 | 291 | break; 292 | } 293 | 294 | default: 295 | NSLog(@"unknow http method"); 296 | break; 297 | } 298 | 299 | // 任务队列 300 | if (requestTask != nil 301 | && requestBean != nil 302 | && [requestBean taskKey] !=nil) { 303 | 304 | [[self shareInstance].taskStack setObject:requestTask forKey:[requestBean taskKey]]; 305 | } 306 | } 307 | 308 | + (void)requestWithBean:(__kindof AJRequestBeanBase *)requestBean cacheCallBack:(AJRequestCallBack)cacheCallBack httpCallBack:(AJRequestCallBack)httpCallBack 309 | { 310 | __weak __typeof__(self) weakSelf = self; 311 | [self cacheWithRequestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 312 | 313 | __strong __typeof__(weakSelf) strongSelf = weakSelf; 314 | 315 | // 缓存结果回调 316 | cacheCallBack(responseBean, err); 317 | 318 | if (err != nil) { 319 | 320 | // 没有缓存,发起网络请求 321 | [strongSelf requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 322 | httpCallBack(responseBean, err); 323 | }]; 324 | 325 | }else{ 326 | 327 | if ([requestBean cacheLiveSecond] == 0) { 328 | 329 | // 缓存长期有效,需要发起网络请求 330 | [strongSelf requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 331 | httpCallBack(responseBean, err); 332 | }]; 333 | 334 | }else{ 335 | // 缓存短期有效,无需网络请求 336 | } 337 | } 338 | }]; 339 | } 340 | 341 | + (NSURLSessionDownloadTask *)downloadTaskWithBean:(__kindof AJRequestBeanDownloadTaskBase *)requestBean progress:(AJDownloadProgressCallBack)progressCallBack completion:(AJDownloadCompletionCallBack)completionCallBack 342 | { 343 | // 如果已存在,则不下载 344 | NSString *saveFilePath = [requestBean.saveFilePath stringByAppendingPathComponent:requestBean.saveFileName]; 345 | NSURL *saveFileUrl = [NSURL fileURLWithPath:saveFilePath]; 346 | NSFileManager *fileManager = [NSFileManager defaultManager]; 347 | if ([fileManager fileExistsAtPath:saveFilePath]) { 348 | completionCallBack(saveFileUrl, nil); 349 | return nil; 350 | } 351 | 352 | 353 | NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; 354 | AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; 355 | 356 | NSURL *URL = [NSURL URLWithString:requestBean.fileUrl]; 357 | NSURLRequest *request = [NSURLRequest requestWithURL:URL]; 358 | 359 | NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { 360 | 361 | if (progressCallBack) { 362 | progressCallBack(downloadProgress.totalUnitCount, downloadProgress.completedUnitCount, (downloadProgress.completedUnitCount * 1.0) / (downloadProgress.totalUnitCount * 1.0)); 363 | } 364 | 365 | } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { 366 | 367 | return saveFileUrl; 368 | 369 | } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) { 370 | 371 | if (completionCallBack) { 372 | completionCallBack(filePath, error); 373 | } 374 | 375 | }]; 376 | 377 | [downloadTask resume]; 378 | 379 | return downloadTask; 380 | } 381 | 382 | + (void)cacheWithRequestWithBean:(__kindof AJRequestBeanBase *)requestBean callBack:(AJRequestCallBack)callBack 383 | { 384 | if ([requestBean cacheResponse]) { 385 | 386 | SPTPersistentCache *httpCache = [[AJNetworkConfig shareInstance] globalHttpCache]; 387 | NSString *cacheKey = [requestBean taskKey]; 388 | 389 | __weak __typeof(&*self) weakSelf = self; 390 | [httpCache loadDataForKey:cacheKey withCallback:^(SPTPersistentCacheResponse * _Nonnull response) { 391 | 392 | __strong __typeof__(weakSelf) strongSelf = weakSelf; 393 | 394 | if (response.result == SPTPersistentCacheResponseCodeOperationSucceeded) { 395 | NSData *cacheData = response.record.data; 396 | NSDictionary *jsonDic = [cacheData mj_keyValues]; 397 | 398 | Class responseClass = [strongSelf responseClassWithRequestBean:requestBean]; 399 | AJResponseBeanBase *responseBean = [responseClass mj_objectWithKeyValues:jsonDic]; 400 | responseBean.rawData = jsonDic; 401 | 402 | callBack(responseBean, nil); 403 | 404 | }else{ 405 | 406 | AJError *err = [[AJError alloc] initWithCode:AJErrorCodeCacheInvalid message:@"cache invalid"]; 407 | callBack(nil, err); 408 | } 409 | 410 | } onQueue:dispatch_get_main_queue()]; 411 | 412 | }else{ 413 | 414 | AJError *err = [[AJError alloc] initWithCode:AJErrorCodeNoCache message:@"no cache"]; 415 | callBack(nil, err); 416 | } 417 | } 418 | 419 | + (void)stopRequestTaskWithTaskKey:(NSArray<__kindof NSString *> *)taskKeyArray 420 | { 421 | if (!taskKeyArray) { 422 | return; 423 | } 424 | 425 | for (NSString *taskKey in taskKeyArray) { 426 | 427 | NSURLSessionTask *task = [[self shareInstance].taskStack objectForKey:taskKey]; 428 | if (task) { 429 | 430 | // 任务取消 431 | if (task.state == NSURLSessionTaskStateRunning) { 432 | [task cancel]; 433 | } 434 | 435 | // 从任务队列中移除 436 | [[self shareInstance].taskStack removeObjectForKey:taskKey]; 437 | } 438 | } 439 | } 440 | 441 | #pragma mark - <结果处理> 442 | 443 | + (void)handleSuccessWithRequestBean:(__kindof AJRequestBeanBase *)requestBean response:(id _Nullable) responseObject callBack:(AJRequestCallBack)callBack 444 | { 445 | [AJNetworkLog logWithRequestBean:requestBean json:responseObject]; 446 | 447 | 448 | //TODO: HEAD 请求结果处理有待补充 449 | if ([requestBean httpMethod] == HTTP_METHOD_HEAD) { 450 | callBack(nil, [AJError defaultError]); 451 | return; 452 | } 453 | 454 | if (!responseObject) { 455 | 456 | AJError *err = [[AJError alloc] initWithCode:AJErrorCodeNoResponse message:@"no response data"]; 457 | callBack(nil, err); 458 | [AJNetworkLog logWithContent:@"请求失败:没有数据返回!"]; 459 | return; 460 | } 461 | 462 | Class responseClass = [self responseClassWithRequestBean:requestBean]; 463 | AJResponseBeanBase *responseBean = [responseClass mj_objectWithKeyValues:responseObject]; 464 | responseBean.rawData = responseObject; 465 | 466 | if ([responseBean checkSuccess]) { 467 | 468 | // 缓存 469 | if ([requestBean cacheResponse]) { 470 | [self saveCacheWithRequestBean:requestBean responseObj:responseObject]; 471 | } 472 | 473 | // 成功 474 | callBack(responseBean, nil); 475 | 476 | }else{ 477 | // 失败 478 | NSString *errMsg = [NSString stringWithFormat:@"错误码:%ld", (long)[responseBean statusCode]]; 479 | NSString *responseMsg = [responseBean responseMessage]; 480 | if ((responseMsg != nil) && ![responseMsg isEqualToString:@""] ) { 481 | errMsg = [NSString stringWithFormat:@"%@ -- %@", errMsg, responseMsg]; 482 | } 483 | 484 | [AJNetworkLog logWithContent:[NSString stringWithFormat:@"请求失败:%@", errMsg]]; 485 | 486 | AJError *err = [[AJError alloc] initWithCode:[responseBean statusCode] message:errMsg]; 487 | callBack(responseBean, err); 488 | } 489 | } 490 | 491 | + (void)handleFailureWithError:(NSError *)error callBack:(AJRequestCallBack)callBack 492 | { 493 | [AJNetworkLog logWithContent:[NSString stringWithFormat:@"请求失败:%@", [error description]]]; 494 | 495 | AJError *err = [[AJError alloc] initWithCode:error.code message:error.description]; 496 | callBack(nil, err); 497 | } 498 | 499 | 500 | + (void)saveCacheWithRequestBean:(__kindof AJRequestBeanBase *) requestBean responseObj:(id _Nullable) responseObject 501 | { 502 | SPTPersistentCache *httpCache = [[AJNetworkConfig shareInstance] globalHttpCache]; 503 | 504 | NSData *cacheData = [responseObject mj_JSONData]; 505 | NSString *cacheKey = [requestBean taskKey]; 506 | NSTimeInterval ttl = [requestBean cacheLiveSecond]; 507 | 508 | [httpCache storeData:cacheData forKey:cacheKey ttl:ttl locked:NO withCallback:^(SPTPersistentCacheResponse * _Nonnull response) { 509 | 510 | if (response.result == SPTPersistentCacheResponseCodeOperationSucceeded) { 511 | AJLog(@"#cache data success#: %@", cacheKey); 512 | }else{ 513 | AJLog(@"#cache fail#: %@", [response.error description]); 514 | } 515 | 516 | } onQueue:dispatch_get_main_queue()]; 517 | } 518 | 519 | #pragma mark Hub 520 | + (void)showHub:(AJRequestBeanBase *)requestBean 521 | { 522 | if ([requestBean isShowHub]) { 523 | 524 | id delegate = [AJNetworkConfig shareInstance].hubDelegate; 525 | if ([delegate respondsToSelector:@selector(showHub:)]) { 526 | [delegate showHub:[requestBean hubTips]]; 527 | } 528 | } 529 | } 530 | 531 | + (void)dismissHub:(AJRequestBeanBase *)requestBean 532 | { 533 | if ([requestBean isShowHub]) { 534 | 535 | id delegate = [AJNetworkConfig shareInstance].hubDelegate; 536 | if ([delegate respondsToSelector:@selector(dismissHub)]) { 537 | [delegate dismissHub]; 538 | } 539 | } 540 | } 541 | 542 | @end 543 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJNetworkStatus.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJNetworkStatus.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/10. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, AJNetworkReachabilityStatus) 12 | { 13 | AJNetworkReachabilityStatusUnknown, 14 | AJNetworkReachabilityStatusNotReachable, 15 | AJNetworkReachabilityStatusWWAN, 16 | AJNetworkReachabilityStatusWiFi 17 | }; 18 | 19 | @interface AJNetworkStatus : NSObject 20 | 21 | + (AJNetworkStatus *)shareInstance; 22 | 23 | - (AJNetworkReachabilityStatus)currentStatus; 24 | 25 | - (BOOL)canReachable; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJNetworkStatus.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJNetworkStatus.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/10. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJNetworkStatus.h" 10 | #import "AFNetworkReachabilityManager.h" 11 | 12 | @interface AJNetworkStatus() 13 | @property (nonatomic, strong) AFNetworkReachabilityManager *networkManager; 14 | @end 15 | 16 | @implementation AJNetworkStatus 17 | 18 | + (AJNetworkStatus *)shareInstance 19 | { 20 | static AJNetworkStatus *instance; 21 | static dispatch_once_t onceToken; 22 | dispatch_once(&onceToken, ^{ 23 | instance = [[AJNetworkStatus alloc] init]; 24 | 25 | instance.networkManager = [AFNetworkReachabilityManager manager]; 26 | [instance.networkManager startMonitoring]; 27 | }); 28 | 29 | return instance; 30 | } 31 | 32 | - (AJNetworkReachabilityStatus)currentStatus 33 | { 34 | switch (self.networkManager.networkReachabilityStatus) { 35 | 36 | case AFNetworkReachabilityStatusUnknown: { 37 | return AJNetworkReachabilityStatusUnknown; 38 | } 39 | 40 | case AFNetworkReachabilityStatusNotReachable: { 41 | return AJNetworkReachabilityStatusNotReachable; 42 | } 43 | 44 | case AFNetworkReachabilityStatusReachableViaWWAN: { 45 | return AJNetworkReachabilityStatusWWAN; 46 | } 47 | 48 | case AFNetworkReachabilityStatusReachableViaWiFi: { 49 | return AJNetworkReachabilityStatusWiFi; 50 | } 51 | 52 | default: 53 | return AJNetworkReachabilityStatusUnknown; 54 | } 55 | } 56 | 57 | - (BOOL)canReachable 58 | { 59 | return self.networkManager.reachable; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /AJNetworking/Classes/AJNetworking.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJNetworking.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/18. 6 | // Copyright © 2016年 Joiway. All rights reserved. 7 | // 8 | 9 | #ifndef AJNetworking_h 10 | #define AJNetworking_h 11 | 12 | #import "AJNetworkConfig.h" 13 | #import "AJNetworkManager.h" 14 | #import "AJRequestBeanBase.h" 15 | #import "AJResponseBeanBase.h" 16 | #import "AJRequestBeanDownloadTaskBase.h" 17 | #import "AJRequestBeanProtocol.h" 18 | #import "AJResponseBeanProtocol.h" 19 | #import "AJCacheOptions.h" 20 | #import "AJNetworkStatus.h" 21 | #import "AJError.h" 22 | #import "AJHubProtocol.h" 23 | 24 | #endif /* AJNetworking_h */ 25 | -------------------------------------------------------------------------------- /AJNetworking/Classes/Model/AJRequestBeanBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJRequestBeanBase.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/18. 6 | // Copyright © 2016年 Joiway. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AJRequestBeanProtocol.h" 11 | 12 | @interface AJRequestBeanBase : NSObject 13 | @property (copy, nonatomic, readonly) NSString *taskKey; 14 | @end 15 | -------------------------------------------------------------------------------- /AJNetworking/Classes/Model/AJRequestBeanBase.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJRequestBeanBase.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/18. 6 | // Copyright © 2016年 Joiway. All rights reserved. 7 | // 8 | 9 | #import "AJRequestBeanBase.h" 10 | #import 11 | #import "MJExtension.h" 12 | #import "MD5Util.h" 13 | 14 | static const NSTimeInterval DEFAULT_TIMEOUT = 30.0; 15 | 16 | @implementation AJRequestBeanBase 17 | 18 | - (HTTP_SCHEME)httpScheme 19 | { 20 | return HTTP_SCHEME_HTTP; 21 | } 22 | 23 | - (HTTP_METHOD)httpMethod 24 | { 25 | return HTTP_METHOD_GET; 26 | } 27 | 28 | - (NSTimeInterval)timeout 29 | { 30 | return DEFAULT_TIMEOUT; 31 | } 32 | 33 | - (NSString *)apiHost 34 | { 35 | return [AJNetworkConfig shareInstance].hostUrl; 36 | } 37 | 38 | - (NSString *)apiPath 39 | { 40 | return @""; 41 | } 42 | 43 | - (NSDictionary *)httpHeader 44 | { 45 | return nil; 46 | } 47 | 48 | - (NSString *)requestUrl 49 | { 50 | NSString *scheme = @"http"; 51 | if ([self httpScheme] == HTTP_SCHEME_HTTPS) { 52 | scheme = @"https"; 53 | } 54 | 55 | NSString *baseUrl = [self apiHost]; 56 | NSString *apiPath = [self apiPath]; 57 | NSString *requestUrl = [NSString stringWithFormat:@"%@://%@%@", scheme, baseUrl, apiPath]; 58 | 59 | return requestUrl; 60 | } 61 | 62 | - (AFConstructingBlock)constructingBodyBlock 63 | { 64 | return nil; 65 | } 66 | 67 | - (BOOL)cacheResponse 68 | { 69 | return NO; 70 | } 71 | 72 | - (NSUInteger)cacheLiveSecond 73 | { 74 | return 0; 75 | } 76 | 77 | + (NSArray *)ignoredPropertyNames 78 | { 79 | return @[]; 80 | } 81 | 82 | + (NSArray *)mj_ignoredPropertyNames 83 | { 84 | NSMutableArray *ignoreArray = [NSMutableArray arrayWithArray:[self ignoredPropertyNames]]; 85 | 86 | [ignoreArray addObject:@"taskKey"]; 87 | 88 | // 解决MJExtension最新版本的BUG 89 | [ignoreArray addObject:@"debugDescription"]; 90 | [ignoreArray addObject:@"description"]; 91 | [ignoreArray addObject:@"hash"]; 92 | [ignoreArray addObject:@"superclass"]; 93 | 94 | return ignoreArray; 95 | } 96 | 97 | - (BOOL)isShowHub 98 | { 99 | return NO; 100 | } 101 | 102 | - (NSString *)hubTips 103 | { 104 | return nil; 105 | } 106 | 107 | - (NSString *)responseBeanClassName 108 | { 109 | const char *requestClassName = class_getName([self class]); 110 | NSString *responseBeanNameStr = [[NSString stringWithUTF8String:requestClassName] stringByReplacingOccurrencesOfString:@"Request" withString:@"Response"]; 111 | return responseBeanNameStr; 112 | } 113 | 114 | - (NSString *)taskKey 115 | { 116 | NSString *cacheInfoStr = [NSString stringWithFormat:@"URL:%@ PARAMS:%@", [self requestUrl], [self mj_keyValues]]; 117 | 118 | NSString *key = [MD5Util md5WithoutEncryptionFactor:cacheInfoStr]; 119 | 120 | return key; 121 | } 122 | 123 | - (HTTP_REQUEST_SERIALIZATION)requestSerialization 124 | { 125 | return HTTP_REQUEST_SERIALIZATION_FORM; 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /AJNetworking/Classes/Model/AJRequestBeanDownloadTaskBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDownloadTaskBase.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/30. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJRequestBeanBase.h" 10 | 11 | @interface AJRequestBeanDownloadTaskBase : AJRequestBeanBase 12 | 13 | @property (nonatomic, copy) NSString *fileUrl; 14 | @property (nonatomic, copy) NSString *saveFilePath; 15 | @property (nonatomic, copy) NSString *saveFileName; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /AJNetworking/Classes/Model/AJRequestBeanDownloadTaskBase.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDownloadTaskBase.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/30. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJRequestBeanDownloadTaskBase.h" 10 | 11 | @implementation AJRequestBeanDownloadTaskBase 12 | 13 | + (NSArray *)ignoredPropertyNames 14 | { 15 | return @[@"fileUrl", @"saveFilePath", @"saveFileName"]; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /AJNetworking/Classes/Model/AJRequestBeanProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJRequestBeanProtocol.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/22. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AJNetworkConfig.h" 11 | 12 | @protocol AJRequestBeanProtocol 13 | 14 | /** 15 | * @author aboojan 16 | * 17 | * @brief HTTP协议 18 | * 19 | * @return HTTP or HTTPS 20 | */ 21 | - (HTTP_SCHEME)httpScheme; 22 | 23 | /** 24 | * @author aboojan 25 | * 26 | * @brief HTTP请求方法 27 | * 28 | * @return GET / POST ... 29 | */ 30 | - (HTTP_METHOD)httpMethod; 31 | 32 | /** 33 | * @author aboojan 34 | * 35 | * @brief 请求超时 36 | * 37 | * @return 超时时长 38 | */ 39 | - (NSTimeInterval)timeout; 40 | 41 | /** 42 | * @author aboojan 43 | * 44 | * @brief Api的主域名 45 | * 46 | * @return 域名或IP 47 | */ 48 | - (NSString *)apiHost; 49 | 50 | /** 51 | * @author aboojan 52 | * 53 | * @brief 请求API路径 54 | * 55 | * @return api路径 56 | */ 57 | - (NSString *)apiPath; 58 | 59 | /** 60 | * @author aboojan 61 | * 62 | * @brief HTTP 请求 header 63 | * 64 | * @return 字典型,如果没有返回nil 65 | */ 66 | - (NSDictionary *)httpHeader; 67 | 68 | /** 69 | * @author aboojan 70 | * 71 | * @brief 发起请求的完整链接 72 | * 73 | * @return 完整请求链接 74 | */ 75 | - (NSString *)requestUrl; 76 | 77 | /** 78 | * @author aboojan 79 | * 80 | * @brief 当POST的内容带有文件等富文本时使用 81 | * 82 | * @return MultipartFormData Block 83 | */ 84 | - (AFConstructingBlock)constructingBodyBlock; 85 | 86 | /** 87 | * @author aboojan 88 | * 89 | * @brief 是否缓存请求结果,默认不缓存 90 | * 91 | * @return YES,缓存;NO,不缓存 92 | */ 93 | - (BOOL)cacheResponse; 94 | 95 | /** 96 | * @author aboojan 97 | * 98 | * @brief 缓存有效时间,单位为秒, 默认为0,即长期有效; 99 | * 100 | * @return 有效时间 101 | */ 102 | - (NSUInteger)cacheLiveSecond; 103 | 104 | /** 105 | * @author aboojan 106 | * 107 | * @brief 忽略的请求参数名称数组 108 | * 109 | * @return 忽略参数数组,如:@[@"param1", @"param2"] 110 | */ 111 | + (NSArray<__kindof NSString *> *)ignoredPropertyNames; 112 | 113 | 114 | /** 115 | * @author aboojan 116 | * 117 | * @brief 是否需要显示Loading,默认不显示 118 | * 119 | * @return YES,显示;NO,不显示 120 | */ 121 | - (BOOL)isShowHub; 122 | 123 | 124 | /** 125 | * @author aboojan 126 | * 127 | * @brief Hub提示文案,isShowHub设置为YES时才会生效 128 | * 129 | * @return 提示文案 130 | */ 131 | - (NSString *)hubTips; 132 | 133 | 134 | /** 135 | * @author aboojan 136 | * 137 | * @brief 用于Response JSON解析的目标类名,默认为根据RequestBean解析名称。 138 | * 如果返回nil,则解析为`AJResponseBeanBase`。 139 | * 类名对应的类必须继承自`AJResponseBeanBase`。 140 | * 141 | @return Response JSON解析的目标类名 142 | */ 143 | - (NSString *)responseBeanClassName; 144 | 145 | /** 146 | 网络请求数据序列化格式 147 | 148 | @return HTTP_REQUEST_SERIALIZATION ENUM, 默认是HTTP_REQUEST_SERIALIZATION_FORM 149 | */ 150 | - (HTTP_REQUEST_SERIALIZATION)requestSerialization; 151 | 152 | @end 153 | -------------------------------------------------------------------------------- /AJNetworking/Classes/Model/AJResponseBeanBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJResponseBeanBase.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/18. 6 | // Copyright © 2016年 Joiway. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AJResponseBeanProtocol.h" 11 | #import "AJNetworkConfig.h" 12 | 13 | @interface AJResponseBeanBase : NSObject 14 | @property (nonatomic, strong) id rawData; 15 | @end 16 | -------------------------------------------------------------------------------- /AJNetworking/Classes/Model/AJResponseBeanBase.m: -------------------------------------------------------------------------------- 1 | // 2 | // AJResponseBeanBase.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/18. 6 | // Copyright © 2016年 Joiway. All rights reserved. 7 | // 8 | 9 | #import "AJResponseBeanBase.h" 10 | 11 | @implementation AJResponseBeanBase 12 | 13 | - (NSInteger)statusCode 14 | { 15 | return 0; 16 | } 17 | 18 | - (NSString *)responseMessage 19 | { 20 | return nil; 21 | } 22 | 23 | - (BOOL)checkSuccess 24 | { 25 | return NO; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /AJNetworking/Classes/Model/AJResponseBeanProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // AJResponseBeanProtocol.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/22. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol AJResponseBeanProtocol 12 | 13 | /** 14 | * @author zhongbaojian 15 | * 16 | * @brief 请求结果状态码 17 | * 18 | * @return 状态码 19 | */ 20 | - (NSInteger)statusCode; 21 | 22 | /** 23 | * @author zhongbaojian 24 | * 25 | * @brief 返回提示信息 26 | * 27 | * @return 提示信息 28 | */ 29 | - (NSString *)responseMessage; 30 | 31 | /** 32 | * @author aboojan, 16-03-20 10:03:57 33 | * 34 | * @brief 根据自定义的状态码校验返回结果是否正确 35 | * 36 | * @return YES,正确;NO,错误 37 | */ 38 | - (BOOL)checkSuccess; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /AJNetworking/Classes/Utils/MD5Util.h: -------------------------------------------------------------------------------- 1 | // 2 | // MD5Util.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface MD5Util : NSObject 13 | 14 | /** 15 | * @author aboojan 16 | * 17 | * @brief 使用默认加密因子进行MD5加密 18 | * 19 | * @param targetContent 需要加密的内容 20 | * 21 | * @return 经过MD5之后的内容 22 | */ 23 | + (NSString *)md5WithDefaultEncryptionFactor:(NSString *) targetContent; 24 | 25 | /** 26 | * @author aboojan 27 | * 28 | * @brief 使用目标加密因子进行MD5加密 29 | * 30 | * @param targetContent 需要加密的内容 31 | * @param factor 加密因子 32 | * 33 | * @return MD5之后的内容 34 | */ 35 | + (NSString *)md5WithContent:(NSString *) targetContent encryptionFactor:(NSString *) factor; 36 | 37 | /** 38 | * @author aboojan 39 | * 40 | * @brief 普通MD5加密 41 | * 42 | * @param targetContent 需要加密的内容 43 | * 44 | * @return MD5之后的内容 45 | */ 46 | + (NSString *)md5WithoutEncryptionFactor:(NSString *) targetContent; 47 | 48 | /** 49 | * @author aboojan 50 | * 51 | * @brief 对NSDictionary数据进行MD5 52 | * 53 | * @param targetDictionary 需要进行MD5的Dictionary 54 | * @param factor 加密因子,如果没有加密因子则使用默认加密因子 55 | * 56 | * @return MD5之后的内容 57 | */ 58 | + (NSString *)md5WithDictionary:(NSDictionary *)targetDictionary encryptionFactor:(NSString *)factor; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /AJNetworking/Classes/Utils/MD5Util.m: -------------------------------------------------------------------------------- 1 | // 2 | // MD5Util.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "MD5Util.h" 10 | #import 11 | #include 12 | 13 | // MD5加密因子 14 | #define MD5_DEFAULT_ENCRYPTION_FACTOR @"123456789" 15 | 16 | @implementation MD5Util 17 | 18 | + (NSString *)md5WithDefaultEncryptionFactor:(NSString *) targetContent 19 | { 20 | 21 | NSString *s1 = [self md5WithoutEncryptionFactor:[targetContent stringByAppendingString:MD5_DEFAULT_ENCRYPTION_FACTOR]]; 22 | NSString *s2 = [self md5WithoutEncryptionFactor:s1]; 23 | return s2; 24 | } 25 | 26 | + (NSString *)md5WithContent:(NSString *) targetContent encryptionFactor:(NSString *) factor 27 | { 28 | 29 | if (factor == nil || [factor isEqualToString:@""]) { 30 | factor = MD5_DEFAULT_ENCRYPTION_FACTOR; 31 | } 32 | 33 | NSString *s1 = [self md5WithoutEncryptionFactor:[targetContent stringByAppendingString:factor]]; 34 | NSString *s2 = [self md5WithoutEncryptionFactor:s1]; 35 | return s2; 36 | } 37 | 38 | 39 | + (NSString *)md5WithoutEncryptionFactor:(NSString *) targetContent 40 | { 41 | const char *cStr = [targetContent UTF8String]; 42 | unsigned char result[16]; 43 | CC_MD5(cStr, (CC_LONG)strlen(cStr), result); 44 | NSString *md5Str = [NSString stringWithFormat: 45 | @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 46 | result[0], result[1], result[2], result[3], 47 | result[4], result[5], result[6], result[7], 48 | result[8], result[9], result[10], result[11], 49 | result[12], result[13], result[14], result[15] 50 | ]; 51 | 52 | return md5Str; 53 | } 54 | 55 | NSInteger letterSorted(id string1,id string2, void *context){ 56 | if (string1&&string2) { 57 | return [string1 compare:string2]; 58 | }else{ 59 | return 0; 60 | } 61 | 62 | } 63 | 64 | + (NSString *)md5WithDictionary:(NSDictionary *) targetDictionary encryptionFactor:(NSString *) factor 65 | { 66 | if ( (targetDictionary != nil) && (targetDictionary.allKeys.count > 0) ) { 67 | 68 | NSArray *keys = targetDictionary.allKeys; 69 | NSArray *sortedKeys = [keys sortedArrayUsingFunction:letterSorted context:NULL]; 70 | NSMutableString *sortedValueString = [[NSMutableString alloc] init]; 71 | 72 | for (NSString *key in sortedKeys) { 73 | 74 | id value = [targetDictionary objectForKey:key]; 75 | 76 | if (value && ![value isEqual:[NSNull null]]) { 77 | 78 | NSString *valueString = @""; 79 | 80 | Class numberClass = objc_getClass("__NSCFNumber"); 81 | Class boolClass = objc_getClass("__NSCFBoolean"); 82 | 83 | if ([value class] == numberClass || [value class] == boolClass) { 84 | 85 | valueString = [value stringValue]; 86 | 87 | }else{ 88 | 89 | valueString = value; 90 | } 91 | 92 | [sortedValueString appendString:valueString]; 93 | } 94 | 95 | } 96 | 97 | return [self md5WithContent:sortedValueString encryptionFactor:factor]; 98 | } 99 | 100 | return @""; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /AJNetworking/Demo/BViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BViewController.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 2016/11/24. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface BViewController : ViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Demo/BViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BViewController.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 2016/11/24. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "BViewController.h" 10 | #import "AJNetworkManager.h" 11 | #import "RequestBeanDemoRegister.h" 12 | #import "ResponseBeanDemoRegister.h" 13 | 14 | @interface BViewController () 15 | @property (nonatomic, strong) NSMutableArray *taskKeyArray; 16 | @end 17 | 18 | @implementation BViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | self.view.backgroundColor = [UIColor orangeColor]; 23 | self.taskKeyArray = [NSMutableArray array]; 24 | 25 | [self performSelector:@selector(closePage) withObject:nil afterDelay:1.0]; 26 | [self sendRequest]; 27 | } 28 | 29 | - (void)closePage 30 | { 31 | [self dismissViewControllerAnimated:YES completion:^{ 32 | // 结束网络请求也可以放到这里 33 | }]; 34 | } 35 | 36 | - (void)dealloc 37 | { 38 | // 可以在控制器释放的时候结束正在进行着的网络请求 39 | // 可以写一个控制器基类,暴露出一个taskKey数组,然后统一在页面关闭时结束网络请求 40 | [AJNetworkManager stopRequestTaskWithTaskKey:self.taskKeyArray]; 41 | 42 | AJLog(@"dealloc"); 43 | } 44 | 45 | - (void)sendRequest 46 | { 47 | [self request1]; 48 | [self request2]; 49 | } 50 | 51 | - (void)request1 52 | { 53 | RequestBeanDemoRegister *requestBean = [RequestBeanDemoRegister new]; 54 | requestBean.userName = @"Github"; 55 | requestBean.pw = @"123456"; 56 | 57 | [self.taskKeyArray addObject:[requestBean taskKey]]; 58 | 59 | [AJNetworkManager requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 60 | 61 | AJLog(@"#request1 Callback#: %@", err); 62 | }]; 63 | } 64 | 65 | - (void)request2 66 | { 67 | RequestBeanDemoRegister *requestBean = [RequestBeanDemoRegister new]; 68 | requestBean.userName = @"Google"; 69 | requestBean.pw = @"123456"; 70 | 71 | [self.taskKeyArray addObject:[requestBean taskKey]]; 72 | 73 | [AJNetworkManager requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 74 | 75 | AJLog(@"#request2 Callback#: %@", err); 76 | }]; 77 | } 78 | 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanDemoBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDemoBase.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJRequestBeanBase.h" 10 | 11 | @interface RequestBeanDemoBase : AJRequestBeanBase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanDemoBase.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDemoBase.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanDemoBase.h" 10 | #import "RequestConfig.h" 11 | 12 | @implementation RequestBeanDemoBase 13 | 14 | - (NSString *)apiPath 15 | { 16 | return [[RequestConfig shareInstance] apiPathWithRequestClass:[self class]]; 17 | } 18 | 19 | - (HTTP_SCHEME)httpScheme 20 | { 21 | return [[RequestConfig shareInstance] httpSchemeWithRequestClass:[self class]]; 22 | } 23 | 24 | - (HTTP_METHOD)httpMethod 25 | { 26 | return [[RequestConfig shareInstance] httpMethodWithRequestClass:[self class]]; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanDemoFilm.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDemoFilm.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/27. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanDemoBase.h" 10 | 11 | @interface RequestBeanDemoFilm : RequestBeanDemoBase 12 | /// 测试码,用于控制返回结果 13 | @property (nonatomic,assign) NSInteger testCode; 14 | @end 15 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanDemoFilm.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDemoFilm.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/27. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanDemoFilm.h" 10 | 11 | @implementation RequestBeanDemoFilm 12 | 13 | - (BOOL)cacheResponse 14 | { 15 | return YES; 16 | } 17 | 18 | - (BOOL)isShowHub 19 | { 20 | return YES; 21 | } 22 | 23 | - (NSString *)hubTips 24 | { 25 | return @"加载中..."; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanDemoLogin.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDemoLogin.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanDemoBase.h" 10 | 11 | @interface RequestBeanDemoLogin : RequestBeanDemoBase 12 | @property (copy, nonatomic) NSString *account; 13 | @property (copy, nonatomic) NSString *pw; 14 | 15 | // 测试参数忽略 16 | @property (copy, nonatomic) NSString *name; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanDemoLogin.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDemoLogin.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanDemoLogin.h" 10 | 11 | @implementation RequestBeanDemoLogin 12 | + (NSArray *)ignoredPropertyNames 13 | { 14 | return @[@"name"]; 15 | } 16 | @end 17 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanDemoNews.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDemoNews.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanDemoBase.h" 10 | 11 | @interface RequestBeanDemoNews : RequestBeanDemoBase 12 | @property (copy, nonatomic) NSString *userId; 13 | @property (copy, nonatomic) NSString *dateTime; 14 | @end 15 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanDemoNews.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDemoNews.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanDemoNews.h" 10 | 11 | @implementation RequestBeanDemoNews 12 | 13 | - (BOOL)cacheResponse 14 | { 15 | return YES; 16 | } 17 | 18 | - (NSUInteger)cacheLiveSecond 19 | { 20 | return 80; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanDemoRegister.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDemoRegister.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanDemoBase.h" 10 | 11 | @interface RequestBeanDemoRegister : RequestBeanDemoBase 12 | 13 | @property (copy, nonatomic) NSString *userName; 14 | @property (copy, nonatomic) NSString *pw; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanDemoRegister.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDemoRegister.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanDemoRegister.h" 10 | 11 | @implementation RequestBeanDemoRegister 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanVersion.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanVersion.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 2016/11/13. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanDemoBase.h" 10 | 11 | @interface RequestBeanVersion : RequestBeanDemoBase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestBeanVersion.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanVersion.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 2016/11/13. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanVersion.h" 10 | 11 | @implementation RequestBeanVersion 12 | - (NSString *)responseBeanClassName 13 | { 14 | // 可以定义一个通用的Response类 15 | return @"ResponseBeanDemo"; 16 | } 17 | @end 18 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestConfig.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AJNetworking.h" 11 | 12 | 13 | @interface RequestConfig : NSObject 14 | 15 | +(RequestConfig *)shareInstance; 16 | 17 | - (NSString *)apiPathWithRequestClass:(Class)requestClass; 18 | - (HTTP_SCHEME)httpSchemeWithRequestClass:(Class)requestClass; 19 | - (HTTP_METHOD)httpMethodWithRequestClass:(Class)requestClass; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestConfig.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestConfig.h" 10 | 11 | static NSString * const KEY_API = @"api"; 12 | static NSString * const KEY_SCHEME = @"scheme"; 13 | static NSString * const KEY_METHOD = @"method"; 14 | 15 | @interface RequestConfig() 16 | @property (nonatomic,strong) NSDictionary *config; 17 | @end 18 | 19 | @implementation RequestConfig 20 | 21 | + (RequestConfig *)shareInstance 22 | { 23 | static RequestConfig *instance; 24 | static dispatch_once_t onceToken; 25 | 26 | dispatch_once(&onceToken, ^{ 27 | instance = [[RequestConfig alloc] init]; 28 | 29 | NSString *configPath = [[NSBundle mainBundle] pathForResource:@"RequestConfig" ofType:@"plist"]; 30 | instance.config = [NSDictionary dictionaryWithContentsOfFile:configPath]; 31 | 32 | }); 33 | 34 | return instance; 35 | } 36 | 37 | - (NSString *)apiPathWithRequestClass:(Class)requestClass 38 | { 39 | NSString *apiPath = self.config[NSStringFromClass(requestClass)][KEY_API]; 40 | return apiPath; 41 | } 42 | 43 | - (HTTP_SCHEME)httpSchemeWithRequestClass:(Class)requestClass 44 | { 45 | NSString *httpScheme = self.config[NSStringFromClass(requestClass)][KEY_SCHEME]; 46 | if ([httpScheme isEqualToString:@"HTTPS"]) { 47 | return HTTP_SCHEME_HTTPS; 48 | }else{ 49 | return HTTP_SCHEME_HTTP; 50 | } 51 | } 52 | 53 | - (HTTP_METHOD)httpMethodWithRequestClass:(Class)requestClass 54 | { 55 | NSString *httpMethod = self.config[NSStringFromClass(requestClass)][KEY_METHOD]; 56 | if ([httpMethod isEqualToString:@"GET"]) { 57 | return HTTP_METHOD_GET; 58 | 59 | }else if ([httpMethod isEqualToString:@"POST"]){ 60 | return HTTP_METHOD_POST; 61 | 62 | }else if ([httpMethod isEqualToString:@"HEAD"]){ 63 | return HTTP_METHOD_HEAD; 64 | 65 | }else if ([httpMethod isEqualToString:@"PUT"]){ 66 | return HTTP_METHOD_PUT; 67 | 68 | }else if ([httpMethod isEqualToString:@"DELETE"]){ 69 | return HTTP_METHOD_DELETE; 70 | 71 | }else{ 72 | return HTTP_METHOD_PATCH; 73 | } 74 | } 75 | 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /AJNetworking/Demo/RequestConfig.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | RequestBeanDemoLogin 6 | 7 | api 8 | /login 9 | scheme 10 | HTTP 11 | method 12 | GET 13 | desc 14 | 接口描述:登陆 15 | 16 | RequestBeanDemoRegister 17 | 18 | api 19 | /register 20 | scheme 21 | HTTP 22 | method 23 | POST 24 | desc 25 | 接口描述:注册 26 | 27 | RequestBeanDemoNews 28 | 29 | api 30 | /news 31 | scheme 32 | HTTP 33 | method 34 | GET 35 | desc 36 | 获取新闻列表 37 | 38 | RequestBeanDemoFilm 39 | 40 | api 41 | /film 42 | scheme 43 | HTTP 44 | method 45 | GET 46 | desc 47 | 接口描述:电影列表 48 | 49 | RequestBeanVersion 50 | 51 | api 52 | /version 53 | scheme 54 | HTTP 55 | method 56 | GET 57 | desc 58 | 接口描述:版本号 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ResponseBeanDemo.h: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDemo.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/22. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJResponseBeanBase.h" 10 | 11 | @interface ResponseBeanDemo : AJResponseBeanBase 12 | @property (nonatomic,strong) NSString *msg; 13 | @property (nonatomic,assign) NSInteger code; 14 | @end 15 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ResponseBeanDemo.m: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDemo.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/22. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanDemo.h" 10 | 11 | @implementation ResponseBeanDemo 12 | - (NSInteger)statusCode 13 | { 14 | return self.code; 15 | } 16 | 17 | - (NSString *)responseMessage 18 | { 19 | return self.msg; 20 | } 21 | 22 | - (BOOL)checkSuccess 23 | { 24 | if (self.code == 1) { 25 | return YES; 26 | }else{ 27 | return NO; 28 | } 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ResponseBeanDemoFilm.h: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDemoFilm.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/27. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanDemo.h" 10 | 11 | @interface Film : NSObject 12 | @property (copy, nonatomic) NSString *name; 13 | @property (copy, nonatomic) NSString *type; 14 | @end 15 | 16 | 17 | @interface ResponseBeanDemoFilm : ResponseBeanDemo 18 | @property (nonatomic,strong) NSArray<__kindof Film *> *data; 19 | @end 20 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ResponseBeanDemoFilm.m: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDemoFilm.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/27. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanDemoFilm.h" 10 | 11 | @implementation Film 12 | @end 13 | 14 | @implementation ResponseBeanDemoFilm 15 | + (NSDictionary *)mj_objectClassInArray 16 | { 17 | return @{@"data":@"Film"}; 18 | } 19 | @end 20 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ResponseBeanDemoLogin.h: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDemoLogin.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanDemo.h" 10 | #import "User.h" 11 | 12 | @interface ResponseBeanDemoLogin : ResponseBeanDemo 13 | @property (nonatomic,strong) User *data; 14 | @end 15 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ResponseBeanDemoLogin.m: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDemoLogin.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanDemoLogin.h" 10 | 11 | @implementation ResponseBeanDemoLogin 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ResponseBeanDemoNews.h: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDemoNews.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanDemo.h" 10 | 11 | @interface News : NSObject 12 | @property (copy, nonatomic) NSString *title; 13 | @property (copy, nonatomic) NSString *content; 14 | @property (copy, nonatomic) NSString *author; 15 | @end 16 | 17 | @interface ResponseBeanDemoNews : ResponseBeanDemo 18 | @property (nonatomic,strong) NSArray<__kindof News *> *data; 19 | @end 20 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ResponseBeanDemoNews.m: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDemoNews.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanDemoNews.h" 10 | 11 | @implementation News 12 | 13 | @end 14 | 15 | @implementation ResponseBeanDemoNews 16 | 17 | + (NSDictionary *)mj_objectClassInArray 18 | { 19 | return @{@"data":@"News"}; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ResponseBeanDemoRegister.h: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDemoRegister.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanDemo.h" 10 | 11 | @interface RegisterUser : NSObject 12 | @property (copy, nonatomic) NSString *userId; 13 | @end 14 | 15 | @interface ResponseBeanDemoRegister : ResponseBeanDemo 16 | @property (nonatomic,strong) RegisterUser *data; 17 | @end 18 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ResponseBeanDemoRegister.m: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDemoRegister.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanDemoRegister.h" 10 | 11 | @implementation RegisterUser 12 | 13 | @end 14 | 15 | @implementation ResponseBeanDemoRegister 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /AJNetworking/Demo/User.h: -------------------------------------------------------------------------------- 1 | // 2 | // User.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface User : NSObject 12 | 13 | @property (copy, nonatomic) NSString *userId; 14 | @property (copy, nonatomic) NSString *name; 15 | @property (nonatomic,assign) NSInteger age; 16 | @property (copy, nonatomic) NSString *gender; 17 | @property (copy, nonatomic) NSString *job; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /AJNetworking/Demo/User.m: -------------------------------------------------------------------------------- 1 | // 2 | // User.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/8/6. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "User.h" 10 | 11 | @implementation User 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/3/19. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /AJNetworking/Demo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/3/19. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "AJNetworkManager.h" 11 | #import "RequestBeanDemoLogin.h" 12 | #import "ResponseBeanDemoLogin.h" 13 | #import "RequestBeanDemoRegister.h" 14 | #import "ResponseBeanDemoRegister.h" 15 | #import "RequestBeanDemoNews.h" 16 | #import "ResponseBeanDemoNews.h" 17 | #import "RequestBeanDemoFilm.h" 18 | #import "ResponseBeanDemoFilm.h" 19 | #import "RequestBeanVersion.h" 20 | #import "MJExtension.h" 21 | #import "BViewController.h" 22 | 23 | @interface ViewController () 24 | 25 | @property (weak, nonatomic) IBOutlet UITextField *accountTF; 26 | @property (weak, nonatomic) IBOutlet UITextField *pwTF; 27 | - (IBAction)loginBtnClick:(UIButton *)sender; 28 | 29 | 30 | @property (weak, nonatomic) IBOutlet UITextField *userNameTF; 31 | @property (weak, nonatomic) IBOutlet UITextField *pwTF1; 32 | - (IBAction)registerBtnClick:(id)sender; 33 | 34 | 35 | @property (weak, nonatomic) IBOutlet UITextField *userIdTF; 36 | @property (weak, nonatomic) IBOutlet UITextField *dateTimeTF; 37 | - (IBAction)readNewsBtnClick:(id)sender; 38 | 39 | 40 | @property (weak, nonatomic) IBOutlet UISegmentedControl *statusSegment; 41 | - (IBAction)filmBtnClick:(id)sender; 42 | 43 | - (IBAction)jumpToPage:(id)sender; 44 | 45 | @end 46 | 47 | @implementation ViewController 48 | 49 | - (void)viewDidLoad { 50 | [super viewDidLoad]; 51 | } 52 | 53 | #pragma mark 自定义Response Bean 示例 54 | - (IBAction)customResponseBeanClassBtnClick:(id)sender 55 | { 56 | RequestBeanVersion *requestBean = [[RequestBeanVersion alloc] init]; 57 | [AJNetworkManager requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 58 | if (!err) { 59 | AJLog(@"%@", responseBean); 60 | }else{ 61 | AJLog(@"%@", [err description]); 62 | } 63 | }]; 64 | } 65 | 66 | 67 | #pragma mark GET请求示例 68 | - (IBAction)loginBtnClick:(UIButton *)sender 69 | { 70 | [self.view endEditing:YES]; 71 | 72 | RequestBeanDemoLogin *requestBean = [[RequestBeanDemoLogin alloc] init]; 73 | requestBean.account = self.accountTF.text; 74 | requestBean.pw = self.pwTF.text; 75 | 76 | //test 77 | requestBean.name = @"aboo"; 78 | 79 | [AJNetworkManager requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 80 | 81 | if (!err) { 82 | 83 | // 返回结果处理 84 | ResponseBeanDemoLogin *response = responseBean; 85 | AJLog(@"user: %@", response.data); 86 | 87 | }else{ 88 | 89 | if (responseBean) { 90 | AJLog(@"请求错误:%ld -- %@", responseBean.statusCode, responseBean.responseMessage); 91 | }else{ 92 | AJLog(@"网络错误,稍后重试"); 93 | } 94 | } 95 | }]; 96 | } 97 | 98 | #pragma mark POST请求示例 99 | - (IBAction)registerBtnClick:(id)sender 100 | { 101 | [self.view endEditing:YES]; 102 | 103 | RequestBeanDemoRegister *requestBean = [RequestBeanDemoRegister new]; 104 | requestBean.userName = self.userNameTF.text; 105 | requestBean.pw = self.pwTF1.text; 106 | 107 | [AJNetworkManager requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 108 | 109 | if (!err) { 110 | 111 | // 结果处理 112 | ResponseBeanDemoRegister *response = responseBean; 113 | AJLog(@"userId:%@", response.data.userId); 114 | } 115 | }]; 116 | 117 | } 118 | 119 | #pragma mark 短期缓存示例 120 | - (IBAction)readNewsBtnClick:(id)sender 121 | { 122 | [self.view endEditing:YES]; 123 | 124 | RequestBeanDemoNews *requestBean = [RequestBeanDemoNews new]; 125 | requestBean.userId = self.userIdTF.text; 126 | requestBean.dateTime = self.dateTimeTF.text; 127 | 128 | [AJNetworkManager requestWithBean:requestBean cacheCallBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 129 | 130 | if (!err) { 131 | 132 | // 读取缓存 133 | AJLog(@"###来自缓存###"); 134 | [self handleNews:responseBean]; 135 | 136 | }else{ 137 | // 读取缓存失败 138 | AJLog(@"%@", [err description]); 139 | } 140 | 141 | } httpCallBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 142 | 143 | if (!err) { 144 | 145 | // 网络请求成功 146 | AJLog(@"###来自网络###"); 147 | [self handleNews:responseBean]; 148 | 149 | }else{ 150 | // 网络请求失败 151 | AJLog(@"%@", [err description]); 152 | } 153 | 154 | }]; 155 | 156 | } 157 | 158 | - (void)handleNews:(ResponseBeanDemoNews *)news 159 | { 160 | for (News *page in news.data) { 161 | AJLog(@"%@ -- %@ -- %@", page.title, page.content, page.author); 162 | } 163 | } 164 | 165 | #pragma mark 长期缓存示例 166 | - (IBAction)filmBtnClick:(id)sender 167 | { 168 | NSInteger testCode = self.statusSegment.selectedSegmentIndex; 169 | 170 | RequestBeanDemoFilm *reqeustBean = [[RequestBeanDemoFilm alloc] init]; 171 | reqeustBean.testCode = testCode; 172 | 173 | /* 174 | * 对于服务器增量更新的设计,可以先读取缓存显示出来,然后根据http请求结果来判断是否更新页面。 175 | */ 176 | 177 | [AJNetworkManager requestWithBean:reqeustBean cacheCallBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 178 | 179 | if (!err) { 180 | 181 | AJLog(@"---来自缓存---"); 182 | [self handleFilm:responseBean]; 183 | } 184 | 185 | } httpCallBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 186 | 187 | if (!err) { 188 | 189 | AJLog(@"---来自网络---"); 190 | [self handleFilm:responseBean]; 191 | } 192 | 193 | }]; 194 | } 195 | 196 | - (void)handleFilm:(ResponseBeanDemoFilm *)films 197 | { 198 | for (Film *film in films.data) { 199 | AJLog(@"%@ -- %@", film.name, film.type); 200 | } 201 | } 202 | 203 | #pragma mark 204 | - (IBAction)jumpToPage:(id)sender 205 | { 206 | BViewController *bPage = [[BViewController alloc] init]; 207 | [self presentViewController:bPage animated:YES completion:^{ 208 | // 209 | }]; 210 | } 211 | 212 | @end 213 | -------------------------------------------------------------------------------- /AJNetworking/Example/Certificate/client_test_local.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbooJan/AJNetworking/cb06bcd954c40a84c40ef7e99eb1443fef5eb55b/AJNetworking/Example/Certificate/client_test_local.p12 -------------------------------------------------------------------------------- /AJNetworking/Example/LoginViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewController.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LoginViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Example/LoginViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewController.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "LoginViewController.h" 10 | #import "RequestBeanLogin.h" 11 | #import "ResponseBeanLogin.h" 12 | #import "AJNetworkManager.h" 13 | #import "TripleDESEncrypt.h" 14 | #import "ResponseBeanAlipayConfig.h" 15 | #import "RequestBeanAlipayConfig.h" 16 | #import "RequestBeanUploadAvatar.h" 17 | #import "ResponseBeanUploadAvatar.h" 18 | #import "ResponseBeanDownloadFile.h" 19 | #import "RequestBeanDownloadFile.h" 20 | #import "AJRequestBeanDownloadTaskBase.h" 21 | #import "MD5Util.h" 22 | 23 | 24 | @interface LoginViewController () 25 | @property (weak, nonatomic) IBOutlet UITextField *accountTF; 26 | @property (weak, nonatomic) IBOutlet UITextField *passwordTF; 27 | 28 | - (IBAction)loginBtnClick:(id)sender; 29 | - (IBAction)httpsTestBtnClick:(id)sender; 30 | - (IBAction)uploadBtnClick:(id)sender; 31 | 32 | - (IBAction)downloadBtnClick:(id)sender; 33 | - (IBAction)suspendDownloadBtnClick:(id)sender; 34 | - (IBAction)cancelDownloadBtnClick:(id)sender; 35 | 36 | @property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask; 37 | @property (nonatomic, assign) BOOL isDownloading; 38 | 39 | @end 40 | 41 | @implementation LoginViewController 42 | 43 | - (void)viewDidLoad { 44 | [super viewDidLoad]; 45 | } 46 | 47 | - (IBAction)loginBtnClick:(id)sender 48 | { 49 | [self.view endEditing:YES]; 50 | 51 | NSString *accountStr = self.accountTF.text; 52 | NSString *pwStr = self.passwordTF.text; 53 | 54 | RequestBeanLogin *requestBean = [[RequestBeanLogin alloc] init]; 55 | requestBean.phone = [TripleDESEncrypt tripleDES:accountStr encryptOrDecrypt:kCCEncrypt]; 56 | requestBean.pwd = [TripleDESEncrypt tripleDES:pwStr encryptOrDecrypt:kCCEncrypt]; 57 | 58 | [AJNetworkManager requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 59 | 60 | if (!err) { 61 | ResponseBeanLogin *response = responseBean; 62 | AJLog(@"#: %@", response.rawData); 63 | } 64 | 65 | }]; 66 | } 67 | 68 | - (IBAction)httpsTestBtnClick:(id)sender 69 | { 70 | // https 测试 71 | 72 | RequestBeanAlipayConfig *requestBean = [[RequestBeanAlipayConfig alloc] init]; 73 | [AJNetworkManager requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 74 | 75 | if (!err) { 76 | ResponseBeanAlipayConfig *response = responseBean; 77 | AlipayConfigBean *configBean = response.obj; 78 | 79 | } 80 | }]; 81 | } 82 | 83 | - (IBAction)uploadBtnClick:(id)sender 84 | { 85 | RequestBeanUploadAvatar *requestBean = [[RequestBeanUploadAvatar alloc] init]; 86 | requestBean.compid = @"1702487"; 87 | requestBean.avatar = [UIImage imageNamed:@"testImg"]; 88 | 89 | [AJNetworkManager requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 90 | 91 | if (!err) { 92 | ResponseBeanUploadAvatar *response = responseBean; 93 | } 94 | }]; 95 | } 96 | 97 | - (IBAction)downloadBtnClick:(id)sender 98 | { 99 | // NSString *fileUrl = @"http://temp.26923.com/2016/pic/000/378/032ad9af805a8e83d8323f515d1d6645.jpg"; 100 | NSString *fileUrl = @"http://125.89.74.165/10/m/m/j/a/mmjazvfnzomddhahggpebnswqfeutw/hc.yinyuetai.com/026601346FEFC3079F2136B68B0ECFD7.flv?sc=5927e705d66bde7b&br=717"; 101 | NSString *fileMD5 = [MD5Util md5WithoutEncryptionFactor:fileUrl]; 102 | 103 | AJRequestBeanDownloadTaskBase *downloadRequest = [[AJRequestBeanDownloadTaskBase alloc] init]; 104 | 105 | downloadRequest.fileUrl = fileUrl; 106 | // downloadRequest.saveFileName = [NSString stringWithFormat:@"%@.jpg", fileMD5]; 107 | 108 | downloadRequest.saveFileName = [NSString stringWithFormat:@"%@.mp4", fileMD5]; 109 | 110 | downloadRequest.saveFilePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; 111 | 112 | self.downloadTask = [AJNetworkManager downloadTaskWithBean:downloadRequest progress:^(int64_t totalUnitCount, int64_t completedUnitCount, double progressRate) { 113 | 114 | AJLog(@"下载进度:%lf", progressRate); 115 | 116 | } completion:^(NSURL *filePath, NSError *error) { 117 | 118 | if (error) { 119 | AJLog(@"下载失败:%@", [error description]); 120 | }else{ 121 | AJLog(@"下载成功:%@", [filePath description]); 122 | } 123 | 124 | }]; 125 | 126 | self.isDownloading = YES; 127 | } 128 | 129 | - (IBAction)suspendDownloadBtnClick:(UIButton *)sender 130 | { 131 | // 暂停下载 132 | if (self.downloadTask) { 133 | 134 | if (self.isDownloading) { 135 | 136 | [self.downloadTask suspend]; 137 | [sender setTitle:@"继续下载" forState:UIControlStateNormal]; 138 | 139 | self.isDownloading = NO; 140 | 141 | }else{ 142 | 143 | [self.downloadTask resume]; 144 | [sender setTitle:@"暂停下载" forState:UIControlStateNormal]; 145 | 146 | self.isDownloading = YES; 147 | } 148 | } 149 | } 150 | 151 | - (IBAction)cancelDownloadBtnClick:(id)sender 152 | { 153 | // 取消下载 154 | if (self.downloadTask) { 155 | [self.downloadTask cancel]; 156 | } 157 | } 158 | @end 159 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/AlipayConfigBean.h: -------------------------------------------------------------------------------- 1 | // 2 | // AlipayConfigBean.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AlipayConfigBean : NSObject 12 | @property (nonatomic,strong) NSString *alipayPubKey; 13 | @property (nonatomic,strong) NSString *partnerPrivKey; 14 | @property (nonatomic,strong) NSString *sellerID; 15 | @property (nonatomic,strong) NSString *partnerID; 16 | @end 17 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/AlipayConfigBean.m: -------------------------------------------------------------------------------- 1 | // 2 | // AlipayConfigBean.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AlipayConfigBean.h" 10 | #import "TripleDESEncrypt.h" 11 | 12 | @implementation AlipayConfigBean 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/CompanyBean.h: -------------------------------------------------------------------------------- 1 | // 2 | // CompanyBean.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/26. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CompanyBean : NSObject 12 | 13 | @property (nonatomic, copy) NSString *province; 14 | @property (nonatomic, copy) NSString *city; 15 | @property (nonatomic, copy) NSString *area; 16 | @property (nonatomic, copy) NSString *user_id; 17 | @property (nonatomic, copy) NSString *email; 18 | @property (nonatomic, copy) NSString *name; 19 | @property (nonatomic, copy) NSString *img; 20 | @property (nonatomic, copy) NSString *introduce; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/CompanyBean.m: -------------------------------------------------------------------------------- 1 | // 2 | // CompanyBean.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/26. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "CompanyBean.h" 10 | 11 | @implementation CompanyBean 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/RequestBeanAlipayConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanAlipayConfig.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJRequestBeanBase.h" 10 | 11 | @interface RequestBeanAlipayConfig : AJRequestBeanBase 12 | @property (nonatomic,assign) NSInteger device; 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/RequestBeanAlipayConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanAlipayConfig.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanAlipayConfig.h" 10 | 11 | @implementation RequestBeanAlipayConfig 12 | 13 | - (HTTP_METHOD)httpMethod 14 | { 15 | return HTTP_METHOD_POST; 16 | } 17 | 18 | - (HTTP_SCHEME)httpScheme 19 | { 20 | return HTTP_SCHEME_HTTPS; 21 | } 22 | 23 | - (NSString *)apiPath 24 | { 25 | return @"/pay/getKey"; 26 | } 27 | 28 | - (NSInteger)device 29 | { 30 | return 1; 31 | } 32 | 33 | - (NSTimeInterval)timeout 34 | { 35 | return 35.0; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/RequestBeanDownloadFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDownloadFile.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/30. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJRequestBeanBase.h" 10 | 11 | @interface RequestBeanDownloadFile : AJRequestBeanBase 12 | @property (nonatomic, copy) NSString *compid; 13 | @property (nonatomic,strong) NSString *job_id; 14 | @property (nonatomic, copy) NSString *timestamp; 15 | @property (nonatomic, assign) NSInteger system; 16 | @property (nonatomic, copy) NSString *versions; 17 | @end 18 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/RequestBeanDownloadFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanDownloadFile.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/30. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanDownloadFile.h" 10 | 11 | @implementation RequestBeanDownloadFile 12 | 13 | - (HTTP_METHOD)httpMethod 14 | { 15 | return HTTP_METHOD_POST; 16 | } 17 | 18 | - (NSString *)apiPath 19 | { 20 | return @"/apply/exportBalance"; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/RequestBeanLogin.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanLogin.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/26. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJRequestBeanBase.h" 10 | 11 | @interface RequestBeanLogin : AJRequestBeanBase 12 | @property (nonatomic, copy) NSString *phone; 13 | @property (nonatomic, copy) NSString *pwd; 14 | @end 15 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/RequestBeanLogin.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanLogin.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/26. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanLogin.h" 10 | 11 | @implementation RequestBeanLogin 12 | 13 | - (HTTP_METHOD)httpMethod 14 | { 15 | return HTTP_METHOD_POST; 16 | } 17 | 18 | - (NSString *)apiPath 19 | { 20 | return @"/company/login"; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/RequestBeanUploadAvatar.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanUploadAvatar.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/29. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJRequestBeanBase.h" 10 | 11 | @interface RequestBeanUploadAvatar : AJRequestBeanBase 12 | 13 | @property (nonatomic, copy) NSString *compid; 14 | 15 | @property (nonatomic, strong) UIImage *avatar; 16 | @end 17 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/RequestBeanUploadAvatar.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestBeanUploadAvatar.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/29. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "RequestBeanUploadAvatar.h" 10 | 11 | @implementation RequestBeanUploadAvatar 12 | 13 | - (NSString *)apiPath 14 | { 15 | return @"/company/updateLogo"; 16 | } 17 | 18 | - (HTTP_METHOD)httpMethod 19 | { 20 | return HTTP_METHOD_POST; 21 | } 22 | 23 | - (NSTimeInterval)timeout 24 | { 25 | return 30.0; 26 | } 27 | 28 | + (NSArray *)mj_ignoredPropertyNames 29 | { 30 | return @[@"avatar"]; 31 | } 32 | 33 | - (AFConstructingBlock)constructingBodyBlock 34 | { 35 | NSData *data = UIImageJPEGRepresentation(self.avatar, 0.8); 36 | NSString *name = @"img"; 37 | NSString *formKey = @"img"; 38 | NSString *type = @"applicaton/octet-stream"; 39 | 40 | return AJConstructingBlockDefine { 41 | [formData appendPartWithFileData:data name:formKey fileName:name mimeType:type]; 42 | }; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/ResponseBeanAlipayConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanAlipayConfig.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanExample.h" 10 | #import "AlipayConfigBean.h" 11 | 12 | @interface ResponseBeanAlipayConfig : ResponseBeanExample 13 | @property (nonatomic,strong) AlipayConfigBean *obj; 14 | @end 15 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/ResponseBeanAlipayConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanAlipayConfig.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanAlipayConfig.h" 10 | 11 | @implementation ResponseBeanAlipayConfig 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/ResponseBeanDownloadFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDownloadFile.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/30. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanExample.h" 10 | 11 | @interface ResponseBeanDownloadFile : ResponseBeanExample 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/ResponseBeanDownloadFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanDownloadFile.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/30. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanDownloadFile.h" 10 | 11 | @implementation ResponseBeanDownloadFile 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/ResponseBeanExample.h: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanExample.h 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/26. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "AJResponseBeanBase.h" 10 | 11 | @interface ResponseBeanExample : AJResponseBeanBase 12 | ///提示语 13 | @property (nonatomic,strong) NSString *msg; 14 | ///状态值 15 | @property (nonatomic,assign) NSInteger status; 16 | @end 17 | -------------------------------------------------------------------------------- /AJNetworking/Example/Model/ResponseBeanExample.m: -------------------------------------------------------------------------------- 1 | // 2 | // ResponseBeanExample.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/26. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "ResponseBeanExample.h" 10 | #import 11 | 12 | #define kDataName @"data." 13 | 14 | @implementation ResponseBeanExample 15 | 16 | - (NSInteger)statusCode 17 | { 18 | return self.status; 19 | } 20 | 21 | - (NSString *)responseMessage 22 | { 23 | return self.msg; 24 | } 25 | 26 | - (BOOL)checkSuccess 27 | { 28 | if (self.status == 0) { 29 | return YES; 30 | }else{ 31 | return NO; 32 | } 33 | } 34 | 35 | + (NSDictionary *)replacedKeyFromPropertyName 36 | { 37 | unsigned int propCount; 38 | objc_property_t* properties = class_copyPropertyList([self class], &propCount); 39 | 40 | NSMutableDictionary *parmas = [[NSMutableDictionary alloc] initWithCapacity:propCount]; 41 | 42 | for (int i=0; i 34 | 35 | 36 | @interface NSData (Base64) 37 | 38 | + (NSData *)dataWithBase64EncodedString:(NSString *)string; 39 | - (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth; 40 | - (NSString *)base64EncodedString; 41 | 42 | @end 43 | 44 | 45 | @interface NSString (Base64) 46 | 47 | + (NSString *)stringWithBase64EncodedString:(NSString *)string; 48 | - (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth; 49 | - (NSString *)base64EncodedString; 50 | - (NSString *)base64DecodedString; 51 | - (NSData *)base64DecodedData; 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /AJNetworking/Example/Utils/Base64/Base64.m: -------------------------------------------------------------------------------- 1 | // 2 | // Base64.m 3 | // 4 | // Version 1.2 5 | // 6 | // Created by Nick Lockwood on 12/01/2012. 7 | // Copyright (C) 2012 Charcoal Design 8 | // 9 | // Distributed under the permissive zlib License 10 | // Get the latest version from here: 11 | // 12 | // https://github.com/nicklockwood/Base64 13 | // 14 | // This software is provided 'as-is', without any express or implied 15 | // warranty. In no event will the authors be held liable for any damages 16 | // arising from the use of this software. 17 | // 18 | // Permission is granted to anyone to use this software for any purpose, 19 | // including commercial applications, and to alter it and redistribute it 20 | // freely, subject to the following restrictions: 21 | // 22 | // 1. The origin of this software must not be misrepresented; you must not 23 | // claim that you wrote the original software. If you use this software 24 | // in a product, an aacknowledgment in the product documentation would be 25 | // appreciated but is not required. 26 | // 27 | // 2. Altered source versions must be plainly marked as such, and must not be 28 | // misrepresented as being the original software. 29 | // 30 | // 3. This notice may not be removed or altered from any source distribution. 31 | // 32 | 33 | #import "Base64.h" 34 | 35 | 36 | #pragma GCC diagnostic ignored "-Wselector" 37 | 38 | 39 | #import 40 | #if !__has_feature(objc_arc) 41 | #error This library requires automatic reference counting 42 | #endif 43 | 44 | 45 | @implementation NSData (Base64) 46 | 47 | + (NSData *)dataWithBase64EncodedString:(NSString *)string 48 | { 49 | if (![string length]) return nil; 50 | 51 | NSData *decoded = nil; 52 | 53 | #if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9 || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0 54 | 55 | if (![NSData instancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) 56 | { 57 | decoded = [[self alloc] initWithBase64Encoding:[string stringByReplacingOccurrencesOfString:@"[^A-Za-z0-9+/=]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [string length])]]; 58 | } 59 | else 60 | 61 | #endif 62 | 63 | { 64 | decoded = [[self alloc] initWithBase64EncodedString:string options:NSDataBase64DecodingIgnoreUnknownCharacters]; 65 | } 66 | 67 | return [decoded length]? decoded: nil; 68 | } 69 | 70 | - (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth 71 | { 72 | if (![self length]) return nil; 73 | 74 | NSString *encoded = nil; 75 | 76 | #if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9 || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0 77 | 78 | if (![NSData instancesRespondToSelector:@selector(base64EncodedStringWithOptions:)]) 79 | { 80 | encoded = [self base64Encoding]; 81 | } 82 | else 83 | 84 | #endif 85 | 86 | { 87 | switch (wrapWidth) 88 | { 89 | case 64: 90 | { 91 | return [self base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; 92 | } 93 | case 76: 94 | { 95 | return [self base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength]; 96 | } 97 | default: 98 | { 99 | encoded = [self base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]; 100 | } 101 | } 102 | } 103 | 104 | if (!wrapWidth || wrapWidth >= [encoded length]) 105 | { 106 | return encoded; 107 | } 108 | 109 | wrapWidth = (wrapWidth / 4) * 4; 110 | NSMutableString *result = [NSMutableString string]; 111 | for (NSUInteger i = 0; i < [encoded length]; i+= wrapWidth) 112 | { 113 | if (i + wrapWidth >= [encoded length]) 114 | { 115 | [result appendString:[encoded substringFromIndex:i]]; 116 | break; 117 | } 118 | [result appendString:[encoded substringWithRange:NSMakeRange(i, wrapWidth)]]; 119 | [result appendString:@"\r\n"]; 120 | } 121 | 122 | return result; 123 | } 124 | 125 | - (NSString *)base64EncodedString 126 | { 127 | return [self base64EncodedStringWithWrapWidth:0]; 128 | } 129 | 130 | @end 131 | 132 | 133 | @implementation NSString (Base64) 134 | 135 | + (NSString *)stringWithBase64EncodedString:(NSString *)string 136 | { 137 | NSData *data = [NSData dataWithBase64EncodedString:string]; 138 | if (data) 139 | { 140 | return [[self alloc] initWithData:data encoding:NSUTF8StringEncoding]; 141 | } 142 | return nil; 143 | } 144 | 145 | - (NSString *)base64EncodedStringWithWrapWidth:(NSUInteger)wrapWidth 146 | { 147 | NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; 148 | return [data base64EncodedStringWithWrapWidth:wrapWidth]; 149 | } 150 | 151 | - (NSString *)base64EncodedString 152 | { 153 | NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; 154 | return [data base64EncodedString]; 155 | } 156 | 157 | - (NSString *)base64DecodedString 158 | { 159 | return [NSString stringWithBase64EncodedString:self]; 160 | } 161 | 162 | - (NSData *)base64DecodedData 163 | { 164 | return [NSData dataWithBase64EncodedString:self]; 165 | } 166 | 167 | @end 168 | -------------------------------------------------------------------------------- /AJNetworking/Example/Utils/NSData+Base64.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Base64.h 3 | // base64 4 | // 5 | // Created by Matt Gallagher on 2009/06/03. 6 | // Copyright 2009 Matt Gallagher. All rights reserved. 7 | // 8 | // This software is provided 'as-is', without any express or implied 9 | // warranty. In no event will the authors be held liable for any damages 10 | // arising from the use of this software. Permission is granted to anyone to 11 | // use this software for any purpose, including commercial applications, and to 12 | // alter it and redistribute it freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would be 17 | // appreciated but is not required. 18 | // 2. Altered source versions must be plainly marked as such, and must not be 19 | // misrepresented as being the original software. 20 | // 3. This notice may not be removed or altered from any source 21 | // distribution. 22 | // 23 | 24 | #import 25 | 26 | void *NewBase64Decode( 27 | const char *inputBuffer, 28 | size_t length, 29 | size_t *outputLength); 30 | 31 | char *NewBase64Encode( 32 | const void *inputBuffer, 33 | size_t length, 34 | bool separateLines, 35 | size_t *outputLength); 36 | 37 | @interface NSData (Base64) 38 | 39 | + (NSData *)dataFromBase64String:(NSString *)aString; 40 | - (NSString *)base64EncodedString; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /AJNetworking/Example/Utils/NSData+Base64.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Base64.m 3 | // base64 4 | // 5 | // Created by Matt Gallagher on 2009/06/03. 6 | // Copyright 2009 Matt Gallagher. All rights reserved. 7 | // 8 | // This software is provided 'as-is', without any express or implied 9 | // warranty. In no event will the authors be held liable for any damages 10 | // arising from the use of this software. Permission is granted to anyone to 11 | // use this software for any purpose, including commercial applications, and to 12 | // alter it and redistribute it freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would be 17 | // appreciated but is not required. 18 | // 2. Altered source versions must be plainly marked as such, and must not be 19 | // misrepresented as being the original software. 20 | // 3. This notice may not be removed or altered from any source 21 | // distribution. 22 | // 23 | 24 | #import "NSData+Base64.h" 25 | 26 | // 27 | // Mapping from 6 bit pattern to ASCII character. 28 | // 29 | static unsigned char base64EncodeLookup[65] = 30 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 31 | 32 | // 33 | // Definition for "masked-out" areas of the base64DecodeLookup mapping 34 | // 35 | #define xx 65 36 | 37 | // 38 | // Mapping from ASCII character to 6 bit pattern. 39 | // 40 | static unsigned char base64DecodeLookup[256] = 41 | { 42 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 43 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 44 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63, 45 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx, 46 | xx, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 47 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx, 48 | xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 49 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx, 50 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 51 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 52 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 53 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 54 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 55 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 56 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 57 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 58 | }; 59 | 60 | // 61 | // Fundamental sizes of the binary and base64 encode/decode units in bytes 62 | // 63 | #define BINARY_UNIT_SIZE 3 64 | #define BASE64_UNIT_SIZE 4 65 | 66 | // 67 | // NewBase64Decode 68 | // 69 | // Decodes the base64 ASCII string in the inputBuffer to a newly malloced 70 | // output buffer. 71 | // 72 | // inputBuffer - the source ASCII string for the decode 73 | // length - the length of the string or -1 (to specify strlen should be used) 74 | // outputLength - if not-NULL, on output will contain the decoded length 75 | // 76 | // returns the decoded buffer. Must be free'd by caller. Length is given by 77 | // outputLength. 78 | // 79 | void *NewBase64Decode( 80 | const char *inputBuffer, 81 | size_t length, 82 | size_t *outputLength) 83 | { 84 | if (length == -1) 85 | { 86 | length = strlen(inputBuffer); 87 | } 88 | 89 | size_t outputBufferSize = 90 | ((length+BASE64_UNIT_SIZE-1) / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE; 91 | unsigned char *outputBuffer = (unsigned char *)malloc(outputBufferSize); 92 | 93 | size_t i = 0; 94 | size_t j = 0; 95 | while (i < length) 96 | { 97 | // 98 | // Accumulate 4 valid characters (ignore everything else) 99 | // 100 | unsigned char accumulated[BASE64_UNIT_SIZE]; 101 | size_t accumulateIndex = 0; 102 | while (i < length) 103 | { 104 | unsigned char decode = base64DecodeLookup[inputBuffer[i++]]; 105 | if (decode != xx) 106 | { 107 | accumulated[accumulateIndex] = decode; 108 | accumulateIndex++; 109 | 110 | if (accumulateIndex == BASE64_UNIT_SIZE) 111 | { 112 | break; 113 | } 114 | } 115 | } 116 | 117 | // 118 | // Store the 6 bits from each of the 4 characters as 3 bytes 119 | // 120 | // (Uses improved bounds checking suggested by Alexandre Colucci) 121 | // 122 | if(accumulateIndex >= 2) 123 | outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4); 124 | if(accumulateIndex >= 3) 125 | outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2); 126 | if(accumulateIndex >= 4) 127 | outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3]; 128 | j += accumulateIndex - 1; 129 | } 130 | 131 | if (outputLength) 132 | { 133 | *outputLength = j; 134 | } 135 | return outputBuffer; 136 | } 137 | 138 | // 139 | // NewBase64Encode 140 | // 141 | // Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced 142 | // output buffer. 143 | // 144 | // inputBuffer - the source data for the encode 145 | // length - the length of the input in bytes 146 | // separateLines - if zero, no CR/LF characters will be added. Otherwise 147 | // a CR/LF pair will be added every 64 encoded chars. 148 | // outputLength - if not-NULL, on output will contain the encoded length 149 | // (not including terminating 0 char) 150 | // 151 | // returns the encoded buffer. Must be free'd by caller. Length is given by 152 | // outputLength. 153 | // 154 | char *NewBase64Encode( 155 | const void *buffer, 156 | size_t length, 157 | bool separateLines, 158 | size_t *outputLength) 159 | { 160 | const unsigned char *inputBuffer = (const unsigned char *)buffer; 161 | 162 | #define MAX_NUM_PADDING_CHARS 2 163 | #define OUTPUT_LINE_LENGTH 64 164 | #define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE) 165 | #define CR_LF_SIZE 2 166 | 167 | // 168 | // Byte accurate calculation of final buffer size 169 | // 170 | size_t outputBufferSize = 171 | ((length / BINARY_UNIT_SIZE) 172 | + ((length % BINARY_UNIT_SIZE) ? 1 : 0)) 173 | * BASE64_UNIT_SIZE; 174 | if (separateLines) 175 | { 176 | outputBufferSize += 177 | (outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE; 178 | } 179 | 180 | // 181 | // Include space for a terminating zero 182 | // 183 | outputBufferSize += 1; 184 | 185 | // 186 | // Allocate the output buffer 187 | // 188 | char *outputBuffer = (char *)malloc(outputBufferSize); 189 | if (!outputBuffer) 190 | { 191 | return NULL; 192 | } 193 | 194 | size_t i = 0; 195 | size_t j = 0; 196 | const size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length; 197 | size_t lineEnd = lineLength; 198 | 199 | while (true) 200 | { 201 | if (lineEnd > length) 202 | { 203 | lineEnd = length; 204 | } 205 | 206 | for (; i + BINARY_UNIT_SIZE - 1 < lineEnd; i += BINARY_UNIT_SIZE) 207 | { 208 | // 209 | // Inner loop: turn 48 bytes into 64 base64 characters 210 | // 211 | outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]; 212 | outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) 213 | | ((inputBuffer[i + 1] & 0xF0) >> 4)]; 214 | outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2) 215 | | ((inputBuffer[i + 2] & 0xC0) >> 6)]; 216 | outputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F]; 217 | } 218 | 219 | if (lineEnd == length) 220 | { 221 | break; 222 | } 223 | 224 | // 225 | // Add the newline 226 | // 227 | outputBuffer[j++] = '\r'; 228 | outputBuffer[j++] = '\n'; 229 | lineEnd += lineLength; 230 | } 231 | 232 | if (i + 1 < length) 233 | { 234 | // 235 | // Handle the single '=' case 236 | // 237 | outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]; 238 | outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) 239 | | ((inputBuffer[i + 1] & 0xF0) >> 4)]; 240 | outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2]; 241 | outputBuffer[j++] = '='; 242 | } 243 | else if (i < length) 244 | { 245 | // 246 | // Handle the double '=' case 247 | // 248 | outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]; 249 | outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0x03) << 4]; 250 | outputBuffer[j++] = '='; 251 | outputBuffer[j++] = '='; 252 | } 253 | outputBuffer[j] = 0; 254 | 255 | // 256 | // Set the output length and return the buffer 257 | // 258 | if (outputLength) 259 | { 260 | *outputLength = j; 261 | } 262 | return outputBuffer; 263 | } 264 | 265 | @implementation NSData (Base64) 266 | 267 | // 268 | // dataFromBase64String: 269 | // 270 | // Creates an NSData object containing the base64 decoded representation of 271 | // the base64 string 'aString' 272 | // 273 | // Parameters: 274 | // aString - the base64 string to decode 275 | // 276 | // returns the autoreleased NSData representation of the base64 string 277 | // 278 | + (NSData *)dataFromBase64String:(NSString *)aString 279 | { 280 | NSData *data = [aString dataUsingEncoding:NSASCIIStringEncoding]; 281 | size_t outputLength; 282 | void *outputBuffer = NewBase64Decode([data bytes], [data length], &outputLength); 283 | NSData *result = [NSData dataWithBytes:outputBuffer length:outputLength]; 284 | free(outputBuffer); 285 | return result; 286 | } 287 | 288 | // 289 | // base64EncodedString 290 | // 291 | // Creates an NSString object that contains the base 64 encoding of the 292 | // receiver's data. Lines are broken at 64 characters long. 293 | // 294 | // returns an autoreleased NSString being the base 64 representation of the 295 | // receiver. 296 | // 297 | - (NSString *)base64EncodedString 298 | { 299 | size_t outputLength = 0; 300 | char *outputBuffer = 301 | NewBase64Encode([self bytes], [self length], true, &outputLength); 302 | 303 | NSString *result = [[NSString alloc]initWithBytes:outputBuffer 304 | length:outputLength 305 | encoding:NSASCIIStringEncoding]; 306 | free(outputBuffer); 307 | return result; 308 | } 309 | 310 | @end 311 | -------------------------------------------------------------------------------- /AJNetworking/Example/Utils/TripleDESEncrypt.h: -------------------------------------------------------------------------------- 1 | // 2 | // TripleDESEncrypt.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | 14 | @interface TripleDESEncrypt : NSObject 15 | 16 | /** 17 | * 内容加密解密 18 | * 19 | * @param plainText 需要加密的内容 20 | * @param encryptOrDecrypt 加密/解密 21 | * 22 | * @return 加密/解密后的内容 23 | */ 24 | + (NSString*)tripleDES:(NSString*)plainText encryptOrDecrypt:(CCOperation)encryptOrDecrypt; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /AJNetworking/Example/Utils/TripleDESEncrypt.m: -------------------------------------------------------------------------------- 1 | // 2 | // TripleDESEncrypt.m 3 | // AJNetworking 4 | // 5 | // Created by 钟宝健 on 16/3/28. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "TripleDESEncrypt.h" 10 | #import "NSData+Base64.h" 11 | 12 | #define kChosenDigestLength CC_SHA1_DIGEST_LENGTH 13 | 14 | #define DESKEY @"12345678912312312" 15 | 16 | @implementation TripleDESEncrypt 17 | 18 | + (NSString*)tripleDES:(NSString*)plainText encryptOrDecrypt:(CCOperation)encryptOrDecrypt 19 | { 20 | const void *vkey = (const void *)[DESKEY UTF8String]; 21 | NSString *result = [self tripleDES:plainText encryptOrDecrypt:encryptOrDecrypt vkey:vkey]; 22 | 23 | return result; 24 | } 25 | 26 | + (NSString*)tripleDES:(NSString*)plainText encryptOrDecrypt:(CCOperation)encryptOrDecrypt vkey:(const void *)vkey 27 | { 28 | const void *vplainText; 29 | size_t plainTextBufferSize; 30 | 31 | if (encryptOrDecrypt == kCCDecrypt)//解密 32 | { 33 | 34 | NSData *EncryptData = [NSData dataFromBase64String:plainText]; 35 | plainTextBufferSize = [EncryptData length]; 36 | vplainText = [EncryptData bytes]; 37 | } 38 | else //加密 39 | { 40 | NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding]; 41 | plainTextBufferSize = [data length]; 42 | vplainText = (const void *)[data bytes]; 43 | } 44 | 45 | CCCryptorStatus ccStatus; 46 | uint8_t *bufferPtr = NULL; 47 | size_t bufferPtrSize = 0; 48 | size_t movedBytes = 0; 49 | 50 | bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1); 51 | bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t)); 52 | memset((void *)bufferPtr, 0x0, bufferPtrSize); 53 | 54 | ccStatus = CCCrypt(encryptOrDecrypt, 55 | kCCAlgorithm3DES, 56 | kCCOptionPKCS7Padding | kCCOptionECBMode, 57 | vkey, 58 | kCCKeySize3DES, 59 | nil, 60 | vplainText, 61 | plainTextBufferSize, 62 | (void *)bufferPtr, 63 | bufferPtrSize, 64 | &movedBytes); 65 | 66 | NSString *result; 67 | 68 | if (encryptOrDecrypt == kCCDecrypt) 69 | { 70 | result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr 71 | length:(NSUInteger)movedBytes] 72 | encoding:NSUTF8StringEncoding]; 73 | } 74 | else 75 | { 76 | NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes]; 77 | result = [myData base64EncodedString]; 78 | } 79 | free(bufferPtr); 80 | 81 | return result; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /AJNetworking/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 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | NSAppTransportSecurity 30 | 31 | NSAllowsArbitraryLoads 32 | 33 | 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 | -------------------------------------------------------------------------------- /AJNetworking/NetworkHub.h: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkHub.h 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 2016/9/25. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AJNetworking.h" 11 | 12 | @interface NetworkHub : NSObject 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /AJNetworking/NetworkHub.m: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkHub.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 2016/9/25. 6 | // Copyright © 2016年 aboojan. All rights reserved. 7 | // 8 | 9 | #import "NetworkHub.h" 10 | 11 | @implementation NetworkHub 12 | 13 | - (void)showHub:(NSString *)tip 14 | { 15 | AJLog(@"显示Hub: %@", tip); 16 | } 17 | 18 | - (void)dismissHub 19 | { 20 | AJLog(@"隐藏Hub"); 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /AJNetworking/client.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbooJan/AJNetworking/cb06bcd954c40a84c40ef7e99eb1443fef5eb55b/AJNetworking/client.p12 -------------------------------------------------------------------------------- /AJNetworking/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AJNetworking 4 | // 5 | // Created by aboojan on 16/3/19. 6 | // Copyright © 2016年 aboojan. 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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 AbooJan 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, "7.0" 2 | 3 | target "AJNetworking" do 4 | 5 | pod "AFNetworking" 6 | pod "MJExtension" 7 | pod "SPTPersistentCache" 8 | 9 | end -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (3.1.0): 3 | - AFNetworking/NSURLSession (= 3.1.0) 4 | - AFNetworking/Reachability (= 3.1.0) 5 | - AFNetworking/Security (= 3.1.0) 6 | - AFNetworking/Serialization (= 3.1.0) 7 | - AFNetworking/UIKit (= 3.1.0) 8 | - AFNetworking/NSURLSession (3.1.0): 9 | - AFNetworking/Reachability 10 | - AFNetworking/Security 11 | - AFNetworking/Serialization 12 | - AFNetworking/Reachability (3.1.0) 13 | - AFNetworking/Security (3.1.0) 14 | - AFNetworking/Serialization (3.1.0) 15 | - AFNetworking/UIKit (3.1.0): 16 | - AFNetworking/NSURLSession 17 | - MJExtension (3.0.13) 18 | - SPTPersistentCache (1.0.0) 19 | 20 | DEPENDENCIES: 21 | - AFNetworking 22 | - MJExtension 23 | - SPTPersistentCache 24 | 25 | SPEC CHECKSUMS: 26 | AFNetworking: 5e0e199f73d8626b11e79750991f5d173d1f8b67 27 | MJExtension: 5932755f451458eefa24239358817f8d291240c7 28 | SPTPersistentCache: c2ab4542796647387441169e352ba5f812128153 29 | 30 | PODFILE CHECKSUM: 1b33c742b248a87bfb2d7c2345e0ce888cea54ce 31 | 32 | COCOAPODS: 1.0.1 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AJNetworking 2 | 3 | [![CocoaPods](https://img.shields.io/cocoapods/v/AJNetworking.svg)](https://cocoapods.org/?q=AJNetworking) 4 | [![ghit.me](https://ghit.me/badge.svg?repo=AbooJan/AJNetworking)](https://ghit.me/repo/AbooJan/AJNetworking) 5 | 6 | AFNetworking 3.0 版本的封装,结合MJExtension框架处理JSON序列化问题 7 | 8 | 项目中使用的网络请求服务器代码使用 `Node.js` 编写:[NetworkTest](https://github.com/AbooJan/NetworkTest) 9 | 10 | 11 | * 网络请求结构图 12 | 13 | ![](./StructureFlow.png) 14 | 15 | 16 | ## 安装 17 | 18 | ``` 19 | pod 'AJNetworking' 20 | ``` 21 | 22 | 23 | ## 使用方法 24 | 25 | #### 一、 网络配置 26 | 1. 全局网络配置,需要使用类 `AJNetworkConfig` 在 `AppDelegate` 中配置. 27 | 28 | ```objective-c 29 | /// 服务器域名 30 | @property (nonatomic, copy) NSString *hostUrl; 31 | /// HTTPS 证书密码 32 | @property (nonatomic, assign) CFStringRef httpsCertificatePassword; 33 | /// HTTPS 证书路径 34 | @property (nonatomic, copy) NSString *httpsCertificatePath; 35 | ``` 36 | 37 | -- 38 | 39 | #### 二、 发起请求 40 | 41 | 1. 新建一个请求类继承自 `AJRequestBeanBase` , 一个响应类继承自 `AJResponseBeanBase` 。 42 | 43 | > #### 命名规则 44 | 45 | > 1. 请求类: `RequestBean` + `业务名称` 46 | 47 | > 2. 响应类: `ResponseBean` + `业务名称` 48 | 49 | > 3. 默认请求类跟响应类的 `业务名称` 必须相同 50 | 51 | > 4. 例如一个登录请求,请求类为:`RequestBeanLogin` , 响应类为:`ResponseBeanLogin` 52 | 53 | > 5. 如果请求类实现了方法:`- (NSString *)responseBeanClassName` , 则可以自定义响应类,名称可以不同,但依然需要继承自 `AJResponseBeanBase` 类。 54 | 55 | 56 | 57 | 2. 请求类里面的成员变量即为发起请求的入参,响应类里面的成员变量即为返回参数。 58 | 59 | 3. 请求类需要遵循协议:`AJRequestBeanProtocol` . 响应类需要遵循协议:`AJResponseBeanProtocol` 60 | 61 | 4. 网络请求的相关配置通过实现协议 `AJRequestBeanProtocol` 的方法。 62 | 63 | 5. 发起请求由类 `AJNetworkManager` 管理,里面负责网络的请求和返回数据的处理,示例: 64 | 65 | ```objective-c 66 | RequestBeanDemoRegister *requestBean = [RequestBeanDemoRegister new]; 67 | requestBean.userName = self.userNameTF.text; 68 | requestBean.pw = self.pwTF1.text; 69 | 70 | [AJNetworkManager requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 71 | 72 | if (!err) { 73 | 74 | // 结果处理 75 | ResponseBeanDemoRegister *response = responseBean; 76 | AJLog(@"userId:%@", response.data.userId); 77 | } 78 | }]; 79 | ``` 80 | 81 | -- 82 | 83 | #### 三、 文件上传 84 | 85 | 1. 请求类需要实现协议 `AJRequestBeanProtocol` 中的方法, 这个参考了 `YTKNetwork` 框架: 86 | 87 | ```objective-c 88 | /** 89 | * @author aboojan 90 | * 91 | * @brief 当POST的内容带有文件等富文本时使用 92 | * 93 | * @return MultipartFormData Block 94 | */ 95 | - (AFConstructingBlock)constructingBodyBlock; 96 | ``` 97 | 98 | 2. 方法实现示例: 99 | 100 | ```objective-c 101 | - (AFConstructingBlock)constructingBodyBlock 102 | { 103 | NSData *data = UIImageJPEGRepresentation(self.avatar, 0.8); 104 | NSString *name = @"img"; 105 | NSString *formKey = @"img"; 106 | NSString *type = @"applicaton/octet-stream"; 107 | 108 | return AJConstructingBlockDefine { 109 | [formData appendPartWithFileData:data name:formKey fileName:name mimeType:type]; 110 | }; 111 | } 112 | ``` 113 | 114 | 3. 文件上传请求示例,跟发起普通请求一样: 115 | 116 | ```objective-c 117 | RequestBeanUploadAvatar *requestBean = [[RequestBeanUploadAvatar alloc] init]; 118 | requestBean.compid = @"1702487"; 119 | requestBean.avatar = [UIImage imageNamed:@"testImg"]; 120 | 121 | [AJNetworkManager requestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 122 | 123 | if (!err) { 124 | ResponseBeanUploadAvatar *response = responseBean; 125 | } 126 | }]; 127 | ``` 128 | 129 | -- 130 | 131 | #### 四、文件下载 132 | 133 | 1. 文件下载跟普通请求不同,需要使用类 `AJNetworkManager` 中的以下方法: 134 | 135 | ```objective-c 136 | /** 137 | * @author aboojan 138 | * 139 | * @brief 文件下载 140 | * 141 | * @param requestBean 文件下载请求Bean 142 | * @param progressCallBack 下载进度回调 143 | * @param completionCallBack 完成回调 144 | * 145 | * @return 当前下载任务线程 146 | */ 147 | + ( NSURLSessionDownloadTask * _Nullable )downloadTaskWithBean:(__kindof RequestBeanDownloadTaskBase * _Nonnull)requestBean progress:(AJDownloadProgressCallBack _Nullable )progressCallBack completion:(AJDownloadCompletionCallBack _Nullable)completionCallBack;; 148 | ``` 149 | 150 | 2. 文件下载请求类使用 `RequestBeanDownloadTaskBase`,使用示例: 151 | 152 | ```objective-c 153 | RequestBeanDownloadTaskBase *downloadRequest = [[RequestBeanDownloadTaskBase alloc] init]; 154 | downloadRequest.fileUrl = @"http://temp.26923.com/2016/pic/000/378/032ad9af805a8e83d8323f515d1d6645.jpg"; 155 | downloadRequest.saveFileName = @"desktop.jpg"; 156 | downloadRequest.saveFilePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; 157 | 158 | [AJNetworkManager downloadTaskWithBean:downloadRequest progress:^(int64_t totalUnitCount, int64_t completedUnitCount, double progressRate) { 159 | 160 | AJLog(@"下载进度:%lf", progressRate); 161 | 162 | } completion:^(NSURL *filePath, NSError *error) { 163 | 164 | if (error) { 165 | AJLog(@"下载失败:%@", [error description]); 166 | }else{ 167 | AJLog(@"下载成功:%@", [filePath description]); 168 | } 169 | 170 | }]; 171 | ``` 172 | 173 | 174 | 3. 下载任务控制, 通过下载请求返回的 `NSURLSessionDownloadTask` 实例来处理。 175 | 176 | ```objective-c 177 | // 暂停任务 178 | [self.downloadTask suspend]; 179 | 180 | // 继续下载 181 | [self.downloadTask resume]; 182 | 183 | // 取消下载 184 | [self.downloadTask cancel]; 185 | ``` 186 | 187 | -- 188 | 189 | #### 五、缓存 190 | 191 | 1. 读取已缓存数据跟发起普通请求类似,使用 `AJNetworkManager` 的以下方法: 192 | 193 | ```objective-c 194 | /** 195 | * @author aboojan 196 | * 197 | * @brief 读取缓存 198 | * 199 | * @param requestBean 请求Bean 200 | * @param callBack 读取缓存回调 201 | */ 202 | + (void)cacheWithRequestWithBean:(__kindof AJRequestBeanBase * _Nonnull)requestBean callBack:(AJRequestCallBack _Nonnull)callBack 203 | ``` 204 | 205 | 2. 如果要缓存请求数据,需要请求类实现协议 `AJRequestBeanProtocol` 的以下方法: 206 | 207 | ```objective-c 208 | /** 209 | * @author aboojan 210 | * 211 | * @brief 是否缓存请求结果,默认不缓存 212 | * 213 | * @return YES,缓存;NO,不缓存 214 | */ 215 | - (BOOL)cacheResponse; 216 | ``` 217 | 218 | 3. 默认缓存是长期有效的,如果需要控制缓存的有效时间,需要请求类实现协议 `AJRequestBeanProtocol` 的以下方法: 219 | 220 | ```objective-c 221 | /** 222 | * @author aboojan 223 | * 224 | * @brief 缓存有效时间,单位为秒, 默认为0,即长期有效; 225 | * 226 | * @return 有效时间 227 | */ 228 | - (NSUInteger)cacheLiveSecond; 229 | ``` 230 | 231 | 4. 发起请求的时候可以先读取缓存,当缓存不存在或已失效的时候才真正发起请求: 232 | 233 | ```objective-c 234 | [AJNetworkManager cacheWithRequestWithBean:requestBean callBack:^(__kindof AJResponseBeanBase * _Nullable responseBean, AJError * _Nullable err) { 235 | 236 | if (!err) { 237 | 238 | // 读取缓存 239 | [self handleReponse:response]; 240 | 241 | }else{ 242 | 243 | // 发起网络请求 244 | [self readFromNetwork]; 245 | } 246 | }]; 247 | ``` 248 | 249 | 5. 目前已把缓存和网络请求结合在了一起,如果设置的是短期缓存,在有效期内不会发起真正的网络请求;如果是长期有效缓存,则会先读取缓存,然后发起网络请求。使用详情可以参考Demo 250 | 251 | ```objective-c 252 | /** 253 | * @author aboojan 254 | * 255 | * @brief 发起网络请求,有缓存 256 | * 257 | * @param requestBean 网络请求参数模式Bean 258 | * @param cacheCallBack 缓存读取回调 259 | * @param httpCallBack 网络请求结果回调 260 | */ 261 | + (void)requestWithBean:(__kindof AJRequestBeanBase * _Nonnull)requestBean 262 | cacheCallBack:(AJRequestCallBack _Nonnull)cacheCallBack 263 | httpCallBack:(AJRequestCallBack _Nonnull)httpCallBack; 264 | ``` 265 | 266 | 267 | -- 268 | 269 | #### 六、全局缓存配置 270 | 1. 缓存配置类 `AJCacheOptions` , 提供3个可选配置项: 271 | 272 | ```objective-c 273 | /** 274 | * @author aboojan 275 | * 276 | * @brief 缓存存放路径 277 | */ 278 | @property (nonatomic, copy) NSString *cachePath; 279 | 280 | /** 281 | * @author aboojan 282 | * 283 | * @brief 是否开启缓存自动回收,默认关闭 284 | */ 285 | @property (nonatomic,assign) BOOL openCacheGC; 286 | 287 | /** 288 | * @author aboojan 289 | * 290 | * @brief 缓存过期时间,最小不能小于60s 291 | */ 292 | @property (nonatomic, assign) NSUInteger globalCacheExpirationSecond; 293 | 294 | /** 295 | * @author aboojan 296 | * 297 | * @brief 缓存自动回收时间,最小不能小于60s 298 | */ 299 | @property (nonatomic, assign) NSUInteger globalCacheGCSecond; 300 | ``` 301 | 302 | 303 | 2. 缓存配置跟网络配置一样,通过类 `AJNetworkConfig` 类设置,例如: 304 | 305 | ```objective-c 306 | AJCacheOptions *cacheOptions = [AJCacheOptions new]; 307 | cacheOptions.cachePath = [documentsPath stringByAppendingPathComponent:@"aj_network_cache"]; 308 | cacheOptions.openCacheGC = YES; 309 | cacheOptions.globalCacheExpirationSecond = 60; 310 | cacheOptions.globalCacheGCSecond = 2 * 60; 311 | networkConfig.cacheOptions = cacheOptions; 312 | ``` 313 | 314 | 315 | -- 316 | 317 | 318 | #### 七、网络状态 319 | 通过类 `AJNetworkStatus` 获取当前网络状态,框架本身在网络配置完之后即开启网络监测。 320 | 321 | ``` 322 | - (AJNetworkReachabilityStatus)currentStatus; 323 | - (BOOL)canReachable; 324 | ``` 325 | 326 | 327 | --- 328 | 329 | 330 | #### 八、网络请求Hub支持 331 | 1. 在 `RequestBean` 中实现以下方法 332 | 333 | ``` 334 | /** 335 | * @author aboojan 336 | * 337 | * @brief 是否需要显示Loading,默认不显示 338 | * 339 | * @return YES,显示;NO,不显示 340 | */ 341 | - (BOOL)isShowHub; 342 | 343 | /** 344 | * @author aboojan 345 | * 346 | * @brief Hub提示文案,isShowHub设置为YES时才会生效 347 | * 348 | @return 提示文案 349 | */ 350 | - (NSString *)hubTips; 351 | ``` 352 | 353 | 2. 通过类 `AJNetworkConfig` 类设置 `hubDelegate` ,然后在 `delegate` 中实现hub的显示。 354 | 355 | ``` 356 | /** 357 | * 显示Hub 358 | * 359 | @param tip hub文案 360 | */ 361 | - (void)showHub:(nullable NSString *)tip; 362 | 363 | /** 364 | * 隐藏Hub 365 | */ 366 | - (void)dismissHub; 367 | ``` 368 | 369 | 370 | --- 371 | 372 | 373 | #### 九、结束网络请求 374 | 1. 通过 `AJNetworkManager` 类的以下方法实现结束网络请求任务 375 | 376 | ``` 377 | /** 378 | 根据 taskKey 结束目标网络请求任务 379 | 380 | @param taskKeyArray 任务Key数组 381 | */ 382 | + (void)stopRequestTaskWithTaskKey:(NSArray<__kindof NSString *> * _Nonnull)taskKeyArray 383 | ``` 384 | 385 | 2. 继承自 `AJRequestBeanBase` 请求数据Bean新增了一个获取 `taskKey` 的成员变量,在Bean赋值后可以获取。 386 | 387 | 3. 这样可以在控制器基类中暴露一个存放 `taskKey` 的数组,然后在通用的页面关闭方法或 `dealloc` 方法中把网络请求结束掉,减少资源占用。 388 | 389 | --- 390 | 391 | ## 感谢 392 | 393 | 依赖框架 | 394 | ------------ | 395 | [AFNetwoking](https://github.com/AFNetworking/AFNetworking) | 396 | [MJExtension](https://github.com/CoderMJLee/MJExtension) | 397 | [SPTPersistentCache](https://github.com/spotify/SPTPersistentCache) | 398 | -------------------------------------------------------------------------------- /StructureFlow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbooJan/AJNetworking/cb06bcd954c40a84c40ef7e99eb1443fef5eb55b/StructureFlow.png --------------------------------------------------------------------------------