筆者前不久終於發佈了本身的APP《小印記》,在此分享一些iOS源碼,若是讀者學到了有用的東西,但願能前往App Store下載《小印記》支持一下筆者,謝謝!javascript
筆者在作《小印記》APP時,使用的是 AFNetworking 3.1 ,經過對AFNetworking的進一步封裝,配合YYCache,實現網絡數據請求。服務器
主要文件以下圖:網絡
附上源碼,僅供參考,讀者可自行對其進行需求改造。session
JKHttpHelper.happ
#import <Foundation/Foundation.h> @interface JKHttpHelper : NSObject // 獲取單例 + (AFHTTPSessionManager * _Nullable)manager; /** * 發送GET請求 * * @param URLString 請求的基本URL * @param parameters 請求的參數字典 * @param success 請求成功的回調 * @param failure 請求失敗的回調 */ + (nullable NSURLSessionDataTask *)GET:(NSString * _Nonnull)URLString parameters:(nullable id)parameters progress:(nullable void (^)(NSProgress * _Nonnull downloadProgress))downloadProgress success:(nullable void (^)(NSURLSessionDataTask * _Nullable task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure; /** * 發送POST請求 * * @param URLString 請求的基本URL * @param parameters 請求的參數字典 * @param success 請求成功的回調 * @param failure 請求失敗的回調 */ + (nullable NSURLSessionDataTask *)POST:(NSString * _Nonnull)URLString parameters:(nullable id)parameters progress:(nullable void (^)(NSProgress * _Nonnull uploadProgress))uploadProgress success:(nullable void (^)(NSURLSessionDataTask * _Nullable task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure; /** * 發送POST請求(數據包含圖片) * * @param URLString 請求的基本URL * @param parameters 請求的參數字典 * @param success 請求成功的回調 * @param failure 請求失敗的回調 */ + (nullable NSURLSessionDataTask *)POST:(NSString * _Nonnull)URLString parameters:(nullable id)parameters constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> _Nullable formData))block progress:(nullable void (^)(NSProgress * _Nonnull uploadProgress))uploadProgress success:(nullable void (^)(NSURLSessionDataTask * _Nullable task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure; @end
JKHttpHelper.murl
#import "JKHttpHelper.h" @implementation JKHttpHelper // 建立單例 + (AFHTTPSessionManager *)manager; { static AFHTTPSessionManager *shareInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; shareInstance = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:BaseHttpURLString] sessionConfiguration:configuration]; //設置請求參數的類型:JSON shareInstance.requestSerializer = [AFJSONRequestSerializer serializer]; //設置服務器返回結果的類型:JSON (AFJSONResponseSerializer,AFHTTPResponseSerializer) shareInstance.responseSerializer = [AFJSONResponseSerializer serializer]; //設置請求的超時時間 shareInstance.requestSerializer.timeoutInterval = 20.0f; //設置ContentType shareInstance.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html", @"text/json", @"text/plain", @"text/javascript", @"text/xml", @"image/jpeg",@"image/png", nil]; // https配置 NSString *cerPath; NSString *cerPathMode = [[NSUserDefaults standardUserDefaults] objectForKey:@"certificate_path"]; if ([cerPathMode isEqualToString:@"bundle"]) { cerPath = [[NSBundle mainBundle] pathForResource:@"wecharactery" ofType:@"cer"]; JKLog(@"--bundle--cerPath:%@", cerPath); } else { cerPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"wecharactery.cer"]; JKLog(@"--document--cerPath:%@", cerPath); } NSData *certData = [NSData dataWithContentsOfFile:cerPath]; AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[[NSSet alloc] initWithObjects:certData, nil]]; NSSet *dataSet = [[NSSet alloc] initWithObjects:certData, nil]; // setPinnedCertificates 設置證書文件(可能不止一個證書) [securityPolicy setPinnedCertificates:dataSet]; // allowInvalidCertificates 是否容許無效證書 [securityPolicy setAllowInvalidCertificates:NO]; // validatesDomainName 是否須要驗證域名 [securityPolicy setValidatesDomainName:YES]; shareInstance.securityPolicy = securityPolicy; }); return shareInstance; } /** * @author 賈則棟, 16-09-14 14:09:38 * * @brief 發送GET請求 * * @param URLString * @param parameters * @param success * @param failure */ + (NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(id)parameters progress:(void (^)(NSProgress * _Nonnull))downloadProgress success:(void (^)(NSURLSessionDataTask * _Nullable, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure { return [[JKHttpHelper manager] GET:URLString parameters:parameters progress:downloadProgress success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { success(task, responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { failure(task, error); }]; } /** * @author 賈則棟, 16-09-14 14:09:10 * * @brief 發送POST請求 * * @param URLString * @param parameters * @param success * @param failure */ + (NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(id)parameters progress:(void (^)(NSProgress * _Nonnull))uploadProgress success:(void (^)(NSURLSessionDataTask * _Nullable, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure { return [[JKHttpHelper manager] POST:URLString parameters:parameters progress:uploadProgress success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { success(task, responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { failure(task, error); }]; } /** * 發送POST請求(數據包含圖片) * * @param URLString 請求的基本URL * @param parameters 請求的參數字典 * @param success 請求成功的回調 * @param failure 請求失敗的回調 */ + (nullable NSURLSessionDataTask *)POST:(NSString * _Nonnull)URLString parameters:(nullable id)parameters constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block progress:(nullable void (^)(NSProgress * _Nonnull uploadProgress))uploadProgress success:(nullable void (^)(NSURLSessionDataTask * _Nullable task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure { return [[JKHttpHelper manager] POST:URLString parameters:parameters constructingBodyWithBlock:block progress:uploadProgress success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { success(task, responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { failure(task, error); }]; }
JKCheckNetworkHelper.h
#import <Foundation/Foundation.h> @interface JKCheckNetworkHelper : NSObject + (void)startMonitoring; + (NSInteger)getNetWorkStatus; @end
JKCheckNetworkHelper.m
#import "JKCheckNetworkHelper.h" @implementation JKCheckNetworkHelper + (void)startMonitoring { [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { // 監測到不一樣網絡的狀況 switch (status) { case AFNetworkReachabilityStatusUnknown: JKLog(@"current network status: Unknown"); break; case AFNetworkReachabilityStatusNotReachable: JKLog(@"current network status: NotReachable"); break; case AFNetworkReachabilityStatusReachableViaWWAN: JKLog(@"current network status: WWAN"); break; case AFNetworkReachabilityStatusReachableViaWiFi: JKLog(@"current network status: WiFi"); break; default: break; } }]; // 開始監聽網絡情況 [[AFNetworkReachabilityManager sharedManager] startMonitoring]; } // 獲取網絡狀態標識 + (NSInteger)getNetWorkStatus { return [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus; } - (void)dealloc { [[AFNetworkReachabilityManager sharedManager] stopMonitoring]; } @end
JKWeCharacteryDataHelper.h
#import <Foundation/Foundation.h> typedef NS_ENUM(NSInteger, RequestMode) { RequestModeGet = 0, // Get請求 RequestModePost // Post請求 }; typedef NS_ENUM(NSInteger, RefreshMode) { RefreshModeFromHeader = 0, // 下拉刷新請求 RefreshModeFromFooter, // 上拉刷新請求 RefreshModeCacheElseNew, // 從緩存加載,沒有則請求 RefreshModeOnlyCache, // 僅從緩存加載 RefreshModeNew // 界面將要顯示時請求 }; @interface JKWeCharacteryDataHelper : NSObject // 獲取、上傳微言數據(不包含圖片) + (nullable NSURLSessionDataTask *)dealWeCharacteryDataWithURL:(NSString * _Nonnull)urlStr Param:(nullable NSMutableDictionary *)param RefreshMode:(RefreshMode)refreshMode RequestMode:(RequestMode)requestMode Success:(nullable void(^)(NSURLSessionDataTask * _Nullable task, id _Nullable responseObject))success Failure:(nullable void(^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure; // 上傳微言數據(包含圖片) + (nullable NSURLSessionDataTask *)uploadWeCharacteryDataWithURL:(NSString * _Nonnull)urlStr Param:(nullable NSMutableDictionary *)param constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> _Nullable formData))block progress:(nullable void (^)(NSProgress * _Nonnull uploadProgress))uploadProgress Success:(nullable void(^)(NSURLSessionDataTask * _Nullable task, id _Nullable responseObject))success Failure:(nullable void(^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure; // 微言數據請求 + (nullable NSURLSessionDataTask *)requestWeCharacteryDataWithURL:(NSString * _Nonnull)urlStr Param:(nullable NSMutableDictionary *)param RefreshMode:(RefreshMode)refreshMode RequestMode:(RequestMode)requestMode Success:(nullable void(^)(NSURLSessionDataTask * _Nullable task, id _Nullable responseObject))success Failure:(nullable void(^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure; // 下載文件 + (nullable NSURLSessionDownloadTask *)downloadFileWithUrl:(NSString * _Nonnull)url progress:(nullable void (^)(NSProgress * _Nonnull downloadProgress))progress destination:(nullable NSURL * _Nonnull (^)(NSURL * _Nullable targetPath, NSURLResponse * _Nullable response))destination completionHandler:(nullable void (^)(NSURLResponse * _Nullable response, NSURL * _Nullable filePath, NSError * _Nonnull error))completionHandler; @end
JKWeCharacteryDataHelper.m
#import "JKWeCharacteryDataHelper.h" #import "JKHttpHelper.h" #import "JKCacheHelper.h" #import "JKCheckNetworkHelper.h" @implementation JKWeCharacteryDataHelper // 獲取、上傳微言數據 + (nullable NSURLSessionDataTask *)dealWeCharacteryDataWithURL:(NSString * _Nonnull)urlStr Param:(nullable NSMutableDictionary *)param RefreshMode:(RefreshMode)refreshMode RequestMode:(RequestMode)requestMode Success:(nullable void(^)(NSURLSessionDataTask * _Nullable task, id _Nullable responseObject))success Failure:(nullable void(^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure { // 獲取網絡狀態 NSInteger networkStatus = [JKCheckNetworkHelper getNetWorkStatus]; if (networkStatus == 0) { refreshMode = RefreshModeCacheElseNew; NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"NetWorkStatus" forKey:NSLocalizedDescriptionKey]; NSError *aError = [NSError errorWithDomain:@"NetWorkError" code:-101 userInfo:userInfo]; failure(nil, aError); } // 獲取緩存數據 id cache = [JKCacheHelper getMemoryCacheWithKey:urlStr]; NSDictionary *object = [[NSDictionary alloc] init]; if (cache) { object = [NSDictionary dictionaryWithObject:cache forKey:@"result"]; } else { object = nil; } switch (refreshMode) { case RefreshModeCacheElseNew: // 從緩存加載,沒有則請求 if (object) { success(nil,object); return nil; } else { break; } case RefreshModeOnlyCache: // 僅從緩存加載 if (object) { success(nil,object); } return nil; case RefreshModeNew: // 界面將要顯示時請求 break; case RefreshModeFromHeader: // 下拉刷新請求 break; case RefreshModeFromFooter: // 上拉刷新請求 break; default: break; } return [self requestWeCharacteryDataWithURL:urlStr Param:param RefreshMode:refreshMode RequestMode:requestMode Success:success Failure:failure]; } // 上傳微言數據(數據包含圖片) + (nullable NSURLSessionDataTask *)uploadWeCharacteryDataWithURL:(NSString * _Nonnull)urlStr Param:(nullable NSMutableDictionary *)param constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> _Nullable formData))block progress:(nullable void (^)(NSProgress * _Nonnull uploadProgress))uploadProgress Success:(nullable void(^)(NSURLSessionDataTask * _Nullable task, id _Nullable responseObject))success Failure:(nullable void(^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure { return [JKHttpHelper POST:urlStr parameters:param constructingBodyWithBlock:block progress:uploadProgress success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { success(task, responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { failure(task, error); }]; } // 微言數據請求 + (nullable NSURLSessionDataTask *)requestWeCharacteryDataWithURL:(NSString * _Nonnull)urlStr Param:(nullable NSMutableDictionary *)param RefreshMode:(RefreshMode)refreshMode RequestMode:(RequestMode)requestMode Success:(nullable void(^)(NSURLSessionDataTask * _Nullable task, id _Nullable responseObject))success Failure:(nullable void(^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure { switch (requestMode) { case RequestModeGet: { switch (refreshMode) { case RefreshModeFromFooter: return [JKHttpHelper GET:urlStr parameters:param progress:^(NSProgress * _Nonnull downloadProgress) { } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { success(task, responseObject); // // 更新緩存 // NSArray *addArr = [NSArray arrayWithArray:responseObject[@"result"]]; // if (addArr.count != 0) { // NSMutableArray *array = [NSMutableArray arrayWithArray:(NSArray *)[JKCacheHelper getMemoryCacheWithKey:urlStr]]; // // 追加到尾部 // [array addObjectsFromArray:addArr]; // // [JKCacheHelper setMemoryCache:array forKey:urlStr withBlock:nil]; // } } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { failure(task, error); }]; break; case RefreshModeFromHeader: return [JKHttpHelper GET:urlStr parameters:param progress:^(NSProgress * _Nonnull downloadProgress) { } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { success(task, responseObject); // // 更新緩存 // NSMutableArray *array = [NSMutableArray arrayWithArray:responseObject[@"result"]]; // id cache = [JKCacheHelper getMemoryCacheWithKey:urlStr]; // if (cache) { // // 添加到頭部 // [array addObjectsFromArray:(NSArray *)cache]; // [JKCacheHelper setMemoryCache:array forKey:urlStr withBlock:nil]; // } // else { // [JKCacheHelper setMemoryCache:array forKey:urlStr withBlock:nil]; // } // // 刷新緩存 // NSArray *array = [NSArray arrayWithArray:responseObject[@"result"]]; // [JKCacheHelper setMemoryCache:array forKey:urlStr withBlock:nil]; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { failure(task, error); }]; break; case RefreshModeNew: case RefreshModeCacheElseNew: return [JKHttpHelper GET:urlStr parameters:param progress:^(NSProgress * _Nonnull downloadProgress) { } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { success(task, responseObject); // // 刷新緩存 // NSArray *array = [NSArray arrayWithArray:responseObject[@"result"]]; // [JKCacheHelper setMemoryCache:array forKey:urlStr withBlock:nil]; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { failure(task, error); }]; break; default: break; } } break; case RequestModePost: { return [JKHttpHelper POST:urlStr parameters:param progress:^(NSProgress * _Nonnull uploadProgress) { } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { success(task, responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { failure(task, error); }]; } break; default: break; } return nil; } + (nullable NSURLSessionDownloadTask *)downloadFileWithUrl:(NSString * _Nonnull)url progress:(nullable void (^)(NSProgress * _Nonnull downloadProgress))progress destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler { NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; NSURL *URL = [NSURL URLWithString:url]; NSURLRequest *request = [NSURLRequest requestWithURL:URL]; NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { progress(downloadProgress); } destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { return destination(targetPath, response); } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { completionHandler(response, filePath, error); }]; // 調用resume開始工做 [downloadTask resume]; return downloadTask; } @end
封裝好之後,就能夠用一句話來實現數據請求了:
[JKWeCharacteryDataHelper dealWeCharacteryDataWithURL:@"Request URL" Param:param RefreshMode:refreshMode RequestMode:requestMode Success:^(NSURLSessionDataTask *task, id responseObject) { NSLog(@"do something..."); } Failure:^(NSURLSessionDataTask *task, NSError *error) { NSLog(@"do something..."); }];
起碼筆者在用的時候是很方便的,但願能給讀者一些思路上的參考。
最後附上《小印記》截圖,但願讀者多多支持!