第六十二篇、AFN3.0封裝網絡請求框架,支持緩存

1.網絡請求

第一種實現方式:javascript

  功能:GET POST 請求html

緩存邏輯:java

  1.是否要刷新本地緩存,不須要就直接發起無緩存的網絡請求,不然直接讀取本地數據ios

  2.須要刷新本地緩存,先讀取本地數據,有就返回,沒有就發起緩存的網絡請求git

  3.無網絡時直接讀取本地緩存github

 

#import "AFHTTPSessionManager.h"

/**
   *該類默認只要導入頭文件就會自動檢測網絡狀態,且會在沒有網絡和未知網絡的時候,自動從本地數據庫中讀取緩存。
   *數據庫網絡緩存是基於猿題庫公司對FMDB進行封裝的輕量級 key-value 存儲框架
   *詳情請見 https://github.com/yuantiku/YTKKeyValueStore  
   *對該類若有疑問能夠拉個issues
 */
@interface JMHttpRequestMethod : AFHTTPSessionManager

typedef NS_ENUM(NSUInteger, JMRequestSerializer) {
    JMRequestSerializerJSON,     // 設置請求數據爲JSON格式
    JMRequestSerializerPlainText    // 設置請求數據爲普通 text/html
};

typedef NS_ENUM(NSUInteger, JMResponseSerializer) {
    JMResponseSerializerJSON,    // 設置響應數據爲JSON格式
    JMResponseSerializerHTTP,    // 設置響應數據爲二進制格式
    JMResponseSerializerXML      // 設置響應數據爲XML格式
};

#pragma mark - 程序入口設置網絡請求頭API  通常調用一次便可

/**
  設置 請求和響應類型和超時時間
 @param requestType  默認爲請求類型爲JSON格式
 @param responseType 默認響應格式爲JSON格式
 @param timeOut      請求超時時間 默認爲20秒
 */
+(void)setTimeOutWithTime:(NSTimeInterval)timeOut
              requestType:(JMRequestSerializer)requestType
             responseType:(JMResponseSerializer)responseType;

/**
 設置 請求頭
 @param httpBody 根據服務器要求 配置相應的請求體
 */
+ (void)setHttpBodyWithDic:(NSDictionary *)httpBody;

#pragma mark - 網絡工具 API
/**
 獲取當前的網絡狀態
 
 @return YES 有網  NO 沒有聯網
 */
+(BOOL)getCurrentNetWorkStatus;

/**
 獲取網絡緩存 文件大小
 @return size  單位M 默認保留兩位小數 如: 0.12M
 */
+ (NSString *)fileSizeWithDBPath;
/**
 清除全部網絡緩存
 */
+ (void)cleanNetWorkRefreshCache;

#pragma mark -  GET 請求API

/**
 GET 請求  不用傳參 API
 @param url          請求的url
 @param refreshCache 是否對該頁面進行緩存
 @param success      請求成功回調
 @param fail         請求失敗回調
 @return self
 */
+ (JMHttpRequestMethod *)getWithUrl:(NSString *)url
                       refreshCache:(BOOL)refreshCache
                            success:(void(^)(id responseObject))success
                               fail:(void(^)(NSError *error))fail;

/**
 GET 請求 傳參數的API
 @param url          請求的url
 @param refreshCache 是否對該頁面進行緩存
 @param params       請求數據向服務器傳的參數
 @param success        請求成功回調
 @param fail         請求失敗回調
 @return self
 */
+ (JMHttpRequestMethod *)getWithUrl:(NSString *)url
                       refreshCache:(BOOL)refreshCache
                             params:(NSDictionary *)params
                            success:(void(^)(id responseObject))success
                               fail:(void(^)(NSError *error))fail;

/**
 GET 請求 帶有進度回調的 API
 @param url               請求的url
 @param refreshCache 是否對該頁面進行緩存
 @param params       請求數據向服務器傳的參數
 @param progress     請求進度回調
 @param success      請求成功回調
 @param fail         請求失敗回調
 @return self
 */
+ (JMHttpRequestMethod *)getWithUrl:(NSString *)url
                       refreshCache:(BOOL)refreshCache
                             params:(NSDictionary *)params
                           progress:(void(^)(int64_t bytesRead, int64_t totalBytesRead))progress
                            success:(void(^)(id responseObject))success
                               fail:(void(^)(NSError *error))fail;


#pragma mark -  POST 請求API


/**
 POST 請求API
 @param url          請求的url
 @param refreshCache 是否對該頁面進行緩存
 @param params       請求數據向服務器傳的參數
 @param success      請求成功回調
 @param fail         請求失敗回調
 @return self
 */
+ (JMHttpRequestMethod *)postWithUrl:(NSString *)url
                        refreshCache:(BOOL)refreshCache
                              params:(NSDictionary *)params
                             success:(void(^)(id responseObject))success
                                fail:(void(^)(NSError *error))fail;


/**
 POST 請求 帶有進度回調的 API
 
 @param url               請求的url
 @param refreshCache 是否對該頁面進行緩存
 @param params       請求數據向服務器傳的參數
 @param progress     請求進度回調
 @param success      請求成功回調
 @param fail         請求失敗回調
 
 @return self
 */
+ (JMHttpRequestMethod *)postWithUrl:(NSString *)url
                        refreshCache:(BOOL)refreshCache
                              params:(NSDictionary *)params
                            progress:(void(^)(int64_t bytesRead, int64_t totalBytesRead))progress
                             success:(void(^)(id responseObject))success
                                fail:(void(^)(NSError *error))fail;



@end

 

#import "JMHttpRequestMethod.h"
#import "YTKKeyValueStore.h"

#define PATH_OF_NetWork    [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]

typedef NS_ENUM(NSUInteger, JMNetworkStatus) {
    JMNetworkStatusUnknown,  //未知的網絡
    JMNetworkStatusNotNetWork, //沒有網絡
    JMNetworkStatusReachableViaWWAN,//手機蜂窩數據網絡
    JMNetworkStatusReachableViaWiFi //WIFI 網絡
};


@interface JMHttpRequestMethod ()
@end

@implementation JMHttpRequestMethod

static NSString *const  httpCache = @"NetworkCache";
static YTKKeyValueStore *_store;
static JMNetworkStatus _status;
static BOOL    _isHasNetWork;

+ (void)load
{
    JMHttpRequestMethod *httpMethod;
    httpMethod.requestSerializer = [AFJSONRequestSerializer serializer];
    //設置請求的超時時間
    httpMethod.requestSerializer.timeoutInterval = 20.f;
    //設置服務器返回結果的類型:JSON (AFJSONResponseSerializer,AFHTTPResponseSerializer)
    httpMethod.responseSerializer = [AFJSONResponseSerializer serializer];
    
    httpMethod.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:
                                                            @"application/json",
                                                            @"text/html",
                                                            @"text/json",
                                                            @"text/plain",
                                                            @"text/javascript",
                                                            @"text/xml", @"image/*", nil];
      [self startMonitoringNetworkStatus];
}

/**
 監測網絡狀態 (在程序入口,調用一次便可)
 */
+ (void)startMonitoringNetworkStatus
{
        AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
        [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
            switch (status)
            {
                case AFNetworkReachabilityStatusUnknown:
                    _isHasNetWork = NO;
                    _status = JMNetworkStatusUnknown;
                    break;
                case AFNetworkReachabilityStatusNotReachable:
                    _isHasNetWork = NO;
                    _status = JMNetworkStatusNotNetWork;
                    NSLog(@"沒有網的狀態");
                    break;
                case AFNetworkReachabilityStatusReachableViaWWAN:
                    _isHasNetWork = YES;
                    _status = JMNetworkStatusReachableViaWWAN;
                    break;
                case AFNetworkReachabilityStatusReachableViaWiFi:
                    _isHasNetWork = YES;
                    _status = JMNetworkStatusReachableViaWiFi;
                    NSLog(@"如今是有網狀態");
                    break;
            }
        }];
        [manager startMonitoring];
}
/**
 設置 請求和響應類型和超時時間
 
 @param requestType  默認爲請求類型爲JSON格式
 @param responseType 默認響應格式爲JSON格式
 @param timeOut      請求超時時間 默認爲20秒
 */
+(void)setTimeOutWithTime:(NSTimeInterval)timeOut
              requestType:(JMRequestSerializer)requestType
             responseType:(JMResponseSerializer)responseType
{
    
    JMHttpRequestMethod *httpMethod;
    httpMethod.requestSerializer.timeoutInterval = timeOut;
    switch (requestType) {
        case JMRequestSerializerJSON:
            httpMethod.requestSerializer = [AFJSONRequestSerializer serializer];
            break;
        case JMRequestSerializerPlainText:
            httpMethod.requestSerializer = [AFHTTPRequestSerializer serializer];
            break;
        default:
            break;
    }
    switch (responseType) {
        case JMResponseSerializerJSON:
            httpMethod.responseSerializer = [AFJSONResponseSerializer serializer];
            break;
            case JMResponseSerializerHTTP:
            httpMethod.responseSerializer = [AFHTTPResponseSerializer serializer];
            break;
            case JMResponseSerializerXML:
            httpMethod.responseSerializer = [AFXMLParserResponseSerializer serializer];
        default:
            break;
    }
}
/**
 設置 請求頭
 
 @param httpBody 根據服務器要求 配置相應的請求體
 */
+ (void)setHttpBodyWithDic:(NSDictionary *)httpBody
{
    JMHttpRequestMethod *httpMethod;
    for (NSString *key in httpBody.allKeys) {
        if (httpBody[key] != nil) {
            [httpMethod.requestSerializer setValue:httpBody[key] forHTTPHeaderField:key];
        }
    }
}


/**
 獲取當前的網絡狀態
 
 @return YES 有網  NO 沒有聯網
 */
+(BOOL)getCurrentNetWorkStatus
{
    return _isHasNetWork;
}

/**
 獲取網絡緩存 文件大小
 
 @return size  單位M
 */
+ (NSString *)fileSizeWithDBPath
{
    NSFileManager* manager = [NSFileManager defaultManager];
    if ([manager fileExistsAtPath:[PATH_OF_NetWork stringByAppendingPathComponent:httpCache]]){
        unsigned  long long  fileSize =  [[manager attributesOfItemAtPath:[PATH_OF_NetWork stringByAppendingPathComponent:httpCache] error:nil] fileSize];
        NSString *size = [NSString stringWithFormat:@"%.2fM",fileSize/1024.0/1024.0];
        return  size;
    }else {
        return @"0M";
    }
    return 0;
}

/**
 清除全部網絡緩存
 */
+ (void)cleanNetWorkRefreshCache
{
    NSError *error;
    BOOL isSuccess =  [[NSFileManager defaultManager]removeItemAtPath:[PATH_OF_NetWork stringByAppendingPathComponent:httpCache] error:&error];
    if (isSuccess) {
        NSLog(@"clean cache file is success");
    }else {
        if ([PATH_OF_NetWork stringByAppendingPathComponent:httpCache]) {
               NSLog(@"error:%@",error.description);
        }else {
            NSLog(@"error: cache file is not exist");
        }
     
    }
}

#pragma mark -  /**************GET 請求API ******************/

+ (JMHttpRequestMethod *)getWithUrl:(NSString *)url
                       refreshCache:(BOOL)refreshCache
                            success:(void(^)(id responseObject))success
                               fail:(void(^)(NSError *error))fail
{
    return [self getWithUrl:url refreshCache:refreshCache params:nil success:success fail:fail];
}
// 多一個params參數
+ (JMHttpRequestMethod *)getWithUrl:(NSString *)url
                       refreshCache:(BOOL)refreshCache
                             params:(NSDictionary *)params
                            success:(void(^)(id responseObject))success
                               fail:(void(^)(NSError *error))fail
{
    return [self getWithUrl:url refreshCache:refreshCache params:params progress:nil success:success fail:fail];
}
// 多一個帶進度回調
+ (JMHttpRequestMethod *)getWithUrl:(NSString *)url
                       refreshCache:(BOOL)refreshCache
                             params:(NSDictionary *)params
                           progress:(void(^)(int64_t bytesRead, int64_t totalBytesRead))progress
                            success:(void(^)(id responseObject))success
                               fail:(void(^)(NSError *error))fail
{
    _store = [[YTKKeyValueStore alloc] initDBWithName:httpCache]; [_store createTableWithName:httpCache];
    JMHttpRequestMethod *request = nil;
    if ([JMHttpRequestMethod getCurrentNetWorkStatus]) {
        if (!refreshCache) {
            [self requestNotCacheWithHttpMethod:0 url:url params:params progress:progress success:success fail:fail];
        }else {
            NSDictionary *dict =   [_store getObjectById:url  fromTable:httpCache];
            if (dict) {
                success(dict);
            }else {
                [[self manager] GET:url parameters:params progress:^(NSProgress * _Nonnull downloadProgress) {
                    progress(downloadProgress.completedUnitCount, downloadProgress.totalUnitCount);
                } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                    [_store putObject:responseObject withId:url intoTable:httpCache];
                    success(responseObject);
                    NSLog(@"\nRequest success, URL: %@\n params:%@\n response:%@\n\n",url,params,responseObject);
                } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                    fail(error);
                    NSLog(@"error = %@",error.description);
                }];
            }
        }
    } else {
        NSDictionary *dict =   [_store getObjectById:url  fromTable:httpCache];
        if (dict) {
            success(dict);
        }else {
            NSLog(@"當前爲無網絡狀態,本地也沒有緩存數據");
        }
    }
    return request;
}
#pragma mark - /*********************** POST 請求API **********************/ + (JMHttpRequestMethod *)postWithUrl:(NSString *)url refreshCache:(BOOL)refreshCache params:(NSDictionary *)params success:(void(^)(id responseObject))success fail:(void(^)(NSError *error))fail { return [self postWithUrl:url refreshCache:refreshCache params:params progress:nil success:success fail:fail]; } + (JMHttpRequestMethod *)postWithUrl:(NSString *)url refreshCache:(BOOL)refreshCache params:(NSDictionary *)params progress:(void(^)(int64_t bytesRead, int64_t totalBytesRead))progress success:(void(^)(id responseObject))success fail:(void(^)(NSError *error))fail { JMHttpRequestMethod *request = nil; if ([JMHttpRequestMethod getCurrentNetWorkStatus]) { if (!refreshCache) { [self requestNotCacheWithHttpMethod:1 url:url params:params progress:progress success:success fail:fail]; }else { NSDictionary *dict = [_store getObjectById:url fromTable:httpCache]; if (dict) { success(dict); }else { [[self manager] POST:url parameters:params progress:^(NSProgress * _Nonnull downloadProgress) { progress(downloadProgress.completedUnitCount, downloadProgress.totalUnitCount); } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { [_store putObject:responseObject withId:url intoTable:httpCache]; success(responseObject); NSLog(@"\nRequest success, URL: %@\n params:%@\n response:%@\n\n",url,params,responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { fail(error); }]; } } } else { NSDictionary *dict = [_store getObjectById:url fromTable:httpCache]; if (dict) { success(dict); }else { NSLog(@"當前爲無網絡狀態,本地也沒有緩存數據"); } } return request; } + (void)requestNotCacheWithHttpMethod:(NSInteger)httpMethod url:(NSString *)url params:(NSDictionary *)params progress:(void(^)(int64_t bytesRead, int64_t totalBytesRead))progress success:(void(^)(id responseObject))success fail:(void(^)(NSError *error))fail { if (httpMethod == 0) { [[self manager]GET:url parameters:params progress:^(NSProgress * _Nonnull downloadProgress) { progress(downloadProgress.completedUnitCount, downloadProgress.totalUnitCount); } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { success(responseObject); NSLog(@"\nRequest success, URL: %@\n params:%@\n response:%@\n\n",url,params,responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { fail(error); }]; }else { [[self manager ]POST:url parameters:params progress:^(NSProgress * _Nonnull uploadProgress) { progress(uploadProgress.completedUnitCount, uploadProgress.totalUnitCount); } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { success(responseObject); NSLog(@"\nRequest success, URL: %@\n params:%@\n response:%@\n\n",url,params,responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { fail(error); }]; } } @end

 

2.數據緩存(FMDB)

#import <Foundation/Foundation.h>

@interface YTKKeyValueItem : NSObject

@property (strong, nonatomic) NSString *itemId;
@property (strong, nonatomic) id itemObject;
@property (strong, nonatomic) NSDate *createdTime;

@end


@interface YTKKeyValueStore : NSObject

- (id)initDBWithName:(NSString *)dbName;

- (id)initWithDBWithPath:(NSString *)dbPath;

- (void)createTableWithName:(NSString *)tableName;

- (void)clearTable:(NSString *)tableName;

- (void)close;

///************************ Put&Get methods *****************************************

- (void)putObject:(id)object withId:(NSString *)objectId intoTable:(NSString *)tableName;

- (id)getObjectById:(NSString *)objectId fromTable:(NSString *)tableName;

- (YTKKeyValueItem *)getYTKKeyValueItemById:(NSString *)objectId fromTable:(NSString *)tableName;

- (void)putString:(NSString *)string withId:(NSString *)stringId intoTable:(NSString *)tableName;

- (NSString *)getStringById:(NSString *)stringId fromTable:(NSString *)tableName;

- (void)putNumber:(NSNumber *)number withId:(NSString *)numberId intoTable:(NSString *)tableName;

- (NSNumber *)getNumberById:(NSString *)numberId fromTable:(NSString *)tableName;

- (NSArray *)getAllItemsFromTable:(NSString *)tableName;

- (void)deleteObjectById:(NSString *)objectId fromTable:(NSString *)tableName;

- (void)deleteObjectsByIdArray:(NSArray *)objectIdArray fromTable:(NSString *)tableName;

- (void)deleteObjectsByIdPrefix:(NSString *)objectIdPrefix fromTable:(NSString *)tableName;


@end

 

#import "YTKKeyValueStore.h"
#import "FMDatabase.h"
#import "FMDatabaseQueue.h"

#ifdef DEBUG
#define debugLog(s, ...) NSLog( @"[%@ in line %d] ➡️➡️➡️%@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#define debugMethod()    NSLog(@"%s", __func__)
#define debugError(s, ...)     NSLog( @"[%@ in line %d] ➡️➡️➡️%@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define debugLog(s,...)
#define debugMethod()
#define debugError(s, ...)
#endif

#define PATH_OF_DOCUMENT    [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]

@implementation YTKKeyValueItem

- (NSString *)description {
    return [NSString stringWithFormat:@"id=%@, value=%@, timeStamp=%@", _itemId, _itemObject, _createdTime];
}

@end

@interface YTKKeyValueStore()

@property (strong, nonatomic) FMDatabaseQueue * dbQueue;

@end

@implementation YTKKeyValueStore

static NSString *const DEFAULT_DB_NAME = @"database.sqlite";

static NSString *const CREATE_TABLE_SQL =
@"CREATE TABLE IF NOT EXISTS %@ ( \
id TEXT NOT NULL, \
json TEXT NOT NULL, \
createdTime TEXT NOT NULL, \
PRIMARY KEY(id)) \
";

static NSString *const UPDATE_ITEM_SQL = @"REPLACE INTO %@ (id, json, createdTime) values (?, ?, ?)";

static NSString *const QUERY_ITEM_SQL = @"SELECT json, createdTime from %@ where id = ? Limit 1";

static NSString *const SELECT_ALL_SQL = @"SELECT * from %@";

static NSString *const CLEAR_ALL_SQL = @"DELETE from %@";

static NSString *const DELETE_ITEM_SQL = @"DELETE from %@ where id = ?";

static NSString *const DELETE_ITEMS_SQL = @"DELETE from %@ where id in ( %@ )";

static NSString *const DELETE_ITEMS_WITH_PREFIX_SQL = @"DELETE from %@ where id like ? ";

+ (BOOL)checkTableName:(NSString *)tableName {
    if (tableName == nil || tableName.length == 0 || [tableName rangeOfString:@" "].location != NSNotFound) {
        debugLog(@"ERROR, table name: %@ format error.", tableName);
        return NO;
    }
    return YES;
}

- (id)init {
    return [self initDBWithName:DEFAULT_DB_NAME];
}

- (id)initDBWithName:(NSString *)dbName {
    self = [super init];
    if (self) {
        NSString * dbPath = [PATH_OF_DOCUMENT stringByAppendingPathComponent:dbName];
        debugLog(@"dbPath = %@", dbPath);
        if (_dbQueue) {
            [self close];
        }
        _dbQueue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
    }
    return self;
}

- (id)initWithDBWithPath:(NSString *)dbPath {
    self = [super init];
    if (self) {
        debugLog(@"dbPath = %@", dbPath);
        if (_dbQueue) {
            [self close];
        }
        _dbQueue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
    }
    return self;
}

- (void)createTableWithName:(NSString *)tableName {
    if ([YTKKeyValueStore checkTableName:tableName] == NO) {
        return;
    }
    NSString * sql = [NSString stringWithFormat:CREATE_TABLE_SQL, tableName];
    __block BOOL result;
    [_dbQueue inDatabase:^(FMDatabase *db) {
        result = [db executeUpdate:sql];
    }];
    if (!result) {
        debugLog(@"ERROR, failed to create table: %@", tableName);
    }
}

- (void)clearTable:(NSString *)tableName {
    if ([YTKKeyValueStore checkTableName:tableName] == NO) {
        return;
    }
    NSString * sql = [NSString stringWithFormat:CLEAR_ALL_SQL, tableName];
    __block BOOL result;
    [_dbQueue inDatabase:^(FMDatabase *db) {
        result = [db executeUpdate:sql];
    }];
    if (!result) {
        debugLog(@"ERROR, failed to clear table: %@", tableName);
    }
}

- (void)putObject:(id)object withId:(NSString *)objectId intoTable:(NSString *)tableName {
    if ([YTKKeyValueStore checkTableName:tableName] == NO) {
        return;
    }
    NSError * error;
    NSData * data = [NSJSONSerialization dataWithJSONObject:object options:0 error:&error];
    if (error) {
        debugLog(@"ERROR, faild to get json data");
        return;
    }
    NSString * jsonString = [[NSString alloc] initWithData:data encoding:(NSUTF8StringEncoding)];
    NSDate * createdTime = [NSDate date];
    NSString * sql = [NSString stringWithFormat:UPDATE_ITEM_SQL, tableName];
    __block BOOL result;
    [_dbQueue inDatabase:^(FMDatabase *db) {
        result = [db executeUpdate:sql, objectId, jsonString, createdTime];
    }];
    if (!result) {
        debugLog(@"ERROR, failed to insert/replace into table: %@", tableName);
    }
}

- (id)getObjectById:(NSString *)objectId fromTable:(NSString *)tableName {
    YTKKeyValueItem * item = [self getYTKKeyValueItemById:objectId fromTable:tableName];
    if (item) {
        return item.itemObject;
    } else {
        return nil;
    }
}

- (YTKKeyValueItem *)getYTKKeyValueItemById:(NSString *)objectId fromTable:(NSString *)tableName {
    if ([YTKKeyValueStore checkTableName:tableName] == NO) {
        return nil;
    }
    NSString * sql = [NSString stringWithFormat:QUERY_ITEM_SQL, tableName];
    __block NSString * json = nil;
    __block NSDate * createdTime = nil;
    [_dbQueue inDatabase:^(FMDatabase *db) {
        FMResultSet * rs = [db executeQuery:sql, objectId];
        if ([rs next]) {
            json = [rs stringForColumn:@"json"];
            createdTime = [rs dateForColumn:@"createdTime"];
        }
        [rs close];
    }];
    if (json) {
        NSError * error;
        id result = [NSJSONSerialization JSONObjectWithData:[json dataUsingEncoding:NSUTF8StringEncoding]
                                                    options:(NSJSONReadingAllowFragments) error:&error];
        if (error) {
            debugLog(@"ERROR, faild to prase to json");
            return nil;
        }
        YTKKeyValueItem * item = [[YTKKeyValueItem alloc] init];
        item.itemId = objectId;
        item.itemObject = result;
        item.createdTime = createdTime;
        return item;
    } else {
        return nil;
    }
}

- (void)putString:(NSString *)string withId:(NSString *)stringId intoTable:(NSString *)tableName {
    if (string == nil) {
        debugLog(@"error, string is nil");
        return;
    }
    [self putObject:@[string] withId:stringId intoTable:tableName];
}

- (NSString *)getStringById:(NSString *)stringId fromTable:(NSString *)tableName {
    NSArray * array = [self getObjectById:stringId fromTable:tableName];
    if (array && [array isKindOfClass:[NSArray class]]) {
        return array[0];
    }
    return nil;
}

- (void)putNumber:(NSNumber *)number withId:(NSString *)numberId intoTable:(NSString *)tableName {
    if (number == nil) {
        debugLog(@"error, number is nil");
        return;
    }
    [self putObject:@[number] withId:numberId intoTable:tableName];
}

- (NSNumber *)getNumberById:(NSString *)numberId fromTable:(NSString *)tableName {
    NSArray * array = [self getObjectById:numberId fromTable:tableName];
    if (array && [array isKindOfClass:[NSArray class]]) {
        return array[0];
    }
    return nil;
}

- (NSArray *)getAllItemsFromTable:(NSString *)tableName {
    if ([YTKKeyValueStore checkTableName:tableName] == NO) {
        return nil;
    }
    NSString * sql = [NSString stringWithFormat:SELECT_ALL_SQL, tableName];
    __block NSMutableArray * result = [NSMutableArray array];
    [_dbQueue inDatabase:^(FMDatabase *db) {
        FMResultSet * rs = [db executeQuery:sql];
        while ([rs next]) {
            YTKKeyValueItem * item = [[YTKKeyValueItem alloc] init];
            item.itemId = [rs stringForColumn:@"id"];
            item.itemObject = [rs stringForColumn:@"json"];
            item.createdTime = [rs dateForColumn:@"createdTime"];
            [result addObject:item];
        }
        [rs close];
    }];
    // parse json string to object
    NSError * error;
    for (YTKKeyValueItem * item in result) {
        error = nil;
        id object = [NSJSONSerialization JSONObjectWithData:[item.itemObject dataUsingEncoding:NSUTF8StringEncoding]
                                                    options:(NSJSONReadingAllowFragments) error:&error];
        if (error) {
            debugLog(@"ERROR, faild to prase to json.");
        } else {
            item.itemObject = object;
        }
    }
    return result;
}

- (void)deleteObjectById:(NSString *)objectId fromTable:(NSString *)tableName {
    if ([YTKKeyValueStore checkTableName:tableName] == NO) {
        return;
    }
    NSString * sql = [NSString stringWithFormat:DELETE_ITEM_SQL, tableName];
    __block BOOL result;
    [_dbQueue inDatabase:^(FMDatabase *db) {
        result = [db executeUpdate:sql, objectId];
    }];
    if (!result) {
        debugLog(@"ERROR, failed to delete item from table: %@", tableName);
    }
}

- (void)deleteObjectsByIdArray:(NSArray *)objectIdArray fromTable:(NSString *)tableName {
    if ([YTKKeyValueStore checkTableName:tableName] == NO) {
        return;
    }
    NSMutableString *stringBuilder = [NSMutableString string];
    for (id objectId in objectIdArray) {
        NSString *item = [NSString stringWithFormat:@" '%@' ", objectId];
        if (stringBuilder.length == 0) {
            [stringBuilder appendString:item];
        } else {
            [stringBuilder appendString:@","];
            [stringBuilder appendString:item];
        }
    }
    NSString *sql = [NSString stringWithFormat:DELETE_ITEMS_SQL, tableName, stringBuilder];
    __block BOOL result;
    [_dbQueue inDatabase:^(FMDatabase *db) {
        result = [db executeUpdate:sql];
    }];
    if (!result) {
        debugLog(@"ERROR, failed to delete items by ids from table: %@", tableName);
    }
}

- (void)deleteObjectsByIdPrefix:(NSString *)objectIdPrefix fromTable:(NSString *)tableName {
    if ([YTKKeyValueStore checkTableName:tableName] == NO) {
        return;
    }
    NSString *sql = [NSString stringWithFormat:DELETE_ITEMS_WITH_PREFIX_SQL, tableName];
    NSString *prefixArgument = [NSString stringWithFormat:@"%@%%", objectIdPrefix];
    __block BOOL result;
    [_dbQueue inDatabase:^(FMDatabase *db) {
        result = [db executeUpdate:sql, prefixArgument];
    }];
    if (!result) {
        debugLog(@"ERROR, failed to delete items by id prefix from table: %@", tableName);
    }
}

- (void)close {
    [_dbQueue close];
    _dbQueue = nil;
}

@end

 

3.使用示例

[JMHttpRequestMethod getWithUrl:url1 refreshCache:YES success:^(id responseObject) {
       
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseObject options:NSJSONWritingPrettyPrinted error:nil];
        self.textView.text = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

       // [JMHttpRequestMethod cleanNetWorkRefreshCache];
         NSLog(@"緩存大小爲%@",  [JMHttpRequestMethod fileSizeWithDBPath]);
    } fail:^(NSError *error) {
        
    }];

 

第二種實現方式:sql

  功能:POST GET Upload download數據庫

#import "HYBNetworking.h"
#import "AFNetworkActivityIndicatorManager.h"
#import "AFNetworking.h"
#import "AFHTTPSessionManager.h"

#import <CommonCrypto/CommonDigest.h>

@interface NSString (md5)

+ (NSString *)hybnetworking_md5:(NSString *)string;

@end

@implementation NSString (md5)

+ (NSString *)hybnetworking_md5:(NSString *)string {
  if (string == nil || [string length] == 0) {
    return nil;
  }
  
  unsigned char digest[CC_MD5_DIGEST_LENGTH], i;
  CC_MD5([string UTF8String], (int)[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding], digest);
  NSMutableString *ms = [NSMutableString string];
  
  for (i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
    [ms appendFormat:@"%02x", (int)(digest[i])];
  }
  
  return [ms copy];
}

@end

static NSString *sg_privateNetworkBaseUrl = nil;
static BOOL sg_isEnableInterfaceDebug = NO;
static BOOL sg_shouldAutoEncode = NO;
static NSDictionary *sg_httpHeaders = nil;
static HYBResponseType sg_responseType = kHYBResponseTypeJSON;
static HYBRequestType  sg_requestType  = kHYBRequestTypePlainText;
static HYBNetworkStatus sg_networkStatus = kHYBNetworkStatusReachableViaWiFi;
static NSMutableArray *sg_requestTasks;
static BOOL sg_cacheGet = YES;
static BOOL sg_cachePost = NO;
static BOOL sg_shouldCallbackOnCancelRequest = YES;
static NSTimeInterval sg_timeout = 60.0f;
static BOOL sg_shoulObtainLocalWhenUnconnected = NO;
static BOOL sg_isBaseURLChanged = YES;
static AFHTTPSessionManager *sg_sharedManager = nil;
static NSUInteger sg_maxCacheSize = 0;

@implementation HYBNetworking

+ (void)load {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    // 嘗試清除緩存
    if (sg_maxCacheSize > 0 && [self totalCacheSize] > 1024 * 1024 * sg_maxCacheSize) {
      [self clearCaches];
    }
  });
}

+ (void)autoToClearCacheWithLimitedToSize:(NSUInteger)mSize {
  sg_maxCacheSize = mSize;
}

+ (void)cacheGetRequest:(BOOL)isCacheGet shoulCachePost:(BOOL)shouldCachePost {
  sg_cacheGet = isCacheGet;
  sg_cachePost = shouldCachePost;
}

+ (void)updateBaseUrl:(NSString *)baseUrl {
  if (![baseUrl isEqualToString:sg_privateNetworkBaseUrl] && baseUrl && baseUrl.length) {
    sg_isBaseURLChanged = YES;
  } else {
    sg_isBaseURLChanged = NO;
  }
  
  sg_privateNetworkBaseUrl = baseUrl;
}

+ (NSString *)baseUrl {
  return sg_privateNetworkBaseUrl;
}

+ (void)setTimeout:(NSTimeInterval)timeout {
  sg_timeout = timeout;
}

+ (void)obtainDataFromLocalWhenNetworkUnconnected:(BOOL)shouldObtain {
  sg_shoulObtainLocalWhenUnconnected = shouldObtain;
  if (sg_shoulObtainLocalWhenUnconnected && (sg_cacheGet || sg_cachePost)) {
    [self detectNetwork];
  }
}

+ (void)enableInterfaceDebug:(BOOL)isDebug {
  sg_isEnableInterfaceDebug = isDebug;
}

+ (BOOL)isDebug {
  return sg_isEnableInterfaceDebug;
}

static inline NSString *cachePath() {
  return [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/HYBNetworkingCaches"];
}

+ (void)clearCaches {
  NSString *directoryPath = cachePath();
  
  if ([[NSFileManager defaultManager] fileExistsAtPath:directoryPath isDirectory:nil]) {
    NSError *error = nil;
    [[NSFileManager defaultManager] removeItemAtPath:directoryPath error:&error];
    
    if (error) {
      NSLog(@"HYBNetworking clear caches error: %@", error);
    } else {
      NSLog(@"HYBNetworking clear caches ok");
    }
  }
}

+ (unsigned long long)totalCacheSize {
  NSString *directoryPath = cachePath();
  BOOL isDir = NO;
  unsigned long long total = 0;
  
  if ([[NSFileManager defaultManager] fileExistsAtPath:directoryPath isDirectory:&isDir]) {
    if (isDir) {
      NSError *error = nil;
      NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directoryPath error:&error];
      
      if (error == nil) {
        for (NSString *subpath in array) {
          NSString *path = [directoryPath stringByAppendingPathComponent:subpath];
          NSDictionary *dict = [[NSFileManager defaultManager] attributesOfItemAtPath:path
                                                                                error:&error];
          if (!error) {
            total += [dict[NSFileSize] unsignedIntegerValue];
          }
        }
      }
    }
  }
  
  return total;
}

+ (NSMutableArray *)allTasks {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    if (sg_requestTasks == nil) {
      sg_requestTasks = [[NSMutableArray alloc] init];
    }
  });
  
  return sg_requestTasks;
}

+ (void)cancelAllRequest {
  @synchronized(self) {
    [[self allTasks] enumerateObjectsUsingBlock:^(HYBURLSessionTask * _Nonnull task, NSUInteger idx, BOOL * _Nonnull stop) {
      if ([task isKindOfClass:[HYBURLSessionTask class]]) {
        [task cancel];
      }
    }];
    
    [[self allTasks] removeAllObjects];
  };
}

+ (void)cancelRequestWithURL:(NSString *)url {
  if (url == nil) {
    return;
  }
  
  @synchronized(self) {
    [[self allTasks] enumerateObjectsUsingBlock:^(HYBURLSessionTask * _Nonnull task, NSUInteger idx, BOOL * _Nonnull stop) {
      if ([task isKindOfClass:[HYBURLSessionTask class]]
          && [task.currentRequest.URL.absoluteString hasSuffix:url]) {
        [task cancel];
        [[self allTasks] removeObject:task];
        return;
      }
    }];
  };
}

+ (void)configRequestType:(HYBRequestType)requestType
             responseType:(HYBResponseType)responseType
      shouldAutoEncodeUrl:(BOOL)shouldAutoEncode
  callbackOnCancelRequest:(BOOL)shouldCallbackOnCancelRequest {
  sg_requestType = requestType;
  sg_responseType = responseType;
  sg_shouldAutoEncode = shouldAutoEncode;
  sg_shouldCallbackOnCancelRequest = shouldCallbackOnCancelRequest;
}

+ (BOOL)shouldEncode {
  return sg_shouldAutoEncode;
}

+ (void)configCommonHttpHeaders:(NSDictionary *)httpHeaders {
  sg_httpHeaders = httpHeaders;
}

+ (HYBURLSessionTask *)getWithUrl:(NSString *)url
                     refreshCache:(BOOL)refreshCache
                          success:(HYBResponseSuccess)success
                             fail:(HYBResponseFail)fail {
  return [self getWithUrl:url
             refreshCache:refreshCache
                   params:nil
                  success:success
                     fail:fail];
}

+ (HYBURLSessionTask *)getWithUrl:(NSString *)url
                     refreshCache:(BOOL)refreshCache
                           params:(NSDictionary *)params
                          success:(HYBResponseSuccess)success
                             fail:(HYBResponseFail)fail {
  return [self getWithUrl:url
             refreshCache:refreshCache
                   params:params
                 progress:nil
                  success:success
                     fail:fail];
}

+ (HYBURLSessionTask *)getWithUrl:(NSString *)url
                     refreshCache:(BOOL)refreshCache
                           params:(NSDictionary *)params
                         progress:(HYBGetProgress)progress
                          success:(HYBResponseSuccess)success
                             fail:(HYBResponseFail)fail {
  return [self _requestWithUrl:url
                  refreshCache:refreshCache
                     httpMedth:1
                        params:params
                      progress:progress
                       success:success
                          fail:fail];
}

+ (HYBURLSessionTask *)postWithUrl:(NSString *)url
                      refreshCache:(BOOL)refreshCache
                            params:(NSDictionary *)params
                           success:(HYBResponseSuccess)success
                              fail:(HYBResponseFail)fail {
  return [self postWithUrl:url
              refreshCache:refreshCache
                    params:params
                  progress:nil
                   success:success
                      fail:fail];
}

+ (HYBURLSessionTask *)postWithUrl:(NSString *)url
                      refreshCache:(BOOL)refreshCache
                            params:(NSDictionary *)params
                          progress:(HYBPostProgress)progress
                           success:(HYBResponseSuccess)success
                              fail:(HYBResponseFail)fail {
  return [self _requestWithUrl:url
                  refreshCache:refreshCache
                     httpMedth:2
                        params:params
                      progress:progress
                       success:success
                          fail:fail];
}

+ (HYBURLSessionTask *)_requestWithUrl:(NSString *)url
                          refreshCache:(BOOL)refreshCache
                             httpMedth:(NSUInteger)httpMethod
                                params:(NSDictionary *)params
                              progress:(HYBDownloadProgress)progress
                               success:(HYBResponseSuccess)success
                                  fail:(HYBResponseFail)fail {
  if ([self shouldEncode]) {
    url = [self encodeUrl:url];
  }

  AFHTTPSessionManager *manager = [self manager];
  NSString *absolute = [self absoluteUrlWithPath:url];
  
  if ([self baseUrl] == nil) {
    if ([NSURL URLWithString:url] == nil) {
      HYBAppLog(@"URLString無效,沒法生成URL。多是URL中有中文,請嘗試Encode URL");
      return nil;
    }
  } else {
    NSURL *absoluteURL = [NSURL URLWithString:absolute];
    
    if (absoluteURL == nil) {
      HYBAppLog(@"URLString無效,沒法生成URL。多是URL中有中文,請嘗試Encode URL");
      return nil;
    }
  }
  
  HYBURLSessionTask *session = nil;
  
  if (httpMethod == 1) {
    if (sg_cacheGet) {
      if (sg_shoulObtainLocalWhenUnconnected) {
        if (sg_networkStatus == kHYBNetworkStatusNotReachable ||  sg_networkStatus == kHYBNetworkStatusUnknown ) {
          id response = [HYBNetworking cahceResponseWithURL:absolute
                                                 parameters:params];
          if (response) {
            if (success) {
              [self successResponse:response callback:success];
              
              if ([self isDebug]) {
                [self logWithSuccessResponse:response
                                         url:absolute
                                      params:params];
              }
            }
            return nil;
          }
        }
      }
      if (!refreshCache) {// 獲取緩存
        id response = [HYBNetworking cahceResponseWithURL:absolute
                                               parameters:params];
        if (response) {
          if (success) {
            [self successResponse:response callback:success];
            
            if ([self isDebug]) {
              [self logWithSuccessResponse:response
                                       url:absolute
                                    params:params];
            }
          }
          return nil;
        }
      }
    }
    
    session = [manager GET:url parameters:params progress:^(NSProgress * _Nonnull downloadProgress) {
      if (progress) {
        progress(downloadProgress.completedUnitCount, downloadProgress.totalUnitCount);
      }
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
      [self successResponse:responseObject callback:success];
      
      if (sg_cacheGet) {
        [self cacheResponseObject:responseObject request:task.currentRequest parameters:params];
      }
      
      [[self allTasks] removeObject:task];
      
      if ([self isDebug]) {
        [self logWithSuccessResponse:responseObject
                                 url:absolute
                              params:params];
      }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
      [[self allTasks] removeObject:task];
      
      if ([error code] < 0 && sg_cacheGet) {// 獲取緩存
        id response = [HYBNetworking cahceResponseWithURL:absolute
                                               parameters:params];
        if (response) {
          if (success) {
            [self successResponse:response callback:success];
            
            if ([self isDebug]) {
              [self logWithSuccessResponse:response
                                       url:absolute
                                    params:params];
            }
          }
        } else {
          [self handleCallbackWithError:error fail:fail];
          
          if ([self isDebug]) {
            [self logWithFailError:error url:absolute params:params];
          }
        }
      } else {
        [self handleCallbackWithError:error fail:fail];
        
        if ([self isDebug]) {
          [self logWithFailError:error url:absolute params:params];
        }
      }
    }];
  } else if (httpMethod == 2) {
    if (sg_cachePost ) {// 獲取緩存
      if (sg_shoulObtainLocalWhenUnconnected) {
        if (sg_networkStatus == kHYBNetworkStatusNotReachable ||  sg_networkStatus == kHYBNetworkStatusUnknown ) {
          id response = [HYBNetworking cahceResponseWithURL:absolute
                                                 parameters:params];
          if (response) {
            if (success) {
              [self successResponse:response callback:success];
              
              if ([self isDebug]) {
                [self logWithSuccessResponse:response
                                         url:absolute
                                      params:params];
              }
            }
            return nil;
          }
        }
      }
      if (!refreshCache) {
        id response = [HYBNetworking cahceResponseWithURL:absolute
                                               parameters:params];
        if (response) {
          if (success) {
            [self successResponse:response callback:success];
            
            if ([self isDebug]) {
              [self logWithSuccessResponse:response
                                       url:absolute
                                    params:params];
            }
          }
          return nil;
        }
      }
    }
    
    session = [manager POST:url parameters:params progress:^(NSProgress * _Nonnull downloadProgress) {
      if (progress) {
        progress(downloadProgress.completedUnitCount, downloadProgress.totalUnitCount);
      }
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
      [self successResponse:responseObject callback:success];
      
      if (sg_cachePost) {
        [self cacheResponseObject:responseObject request:task.currentRequest  parameters:params];
      }
      
      [[self allTasks] removeObject:task];
      
      if ([self isDebug]) {
        [self logWithSuccessResponse:responseObject
                                 url:absolute
                              params:params];
      }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
      [[self allTasks] removeObject:task];
      
      if ([error code] < 0 && sg_cachePost) {// 獲取緩存
        id response = [HYBNetworking cahceResponseWithURL:absolute
                                               parameters:params];
        
        if (response) {
          if (success) {
            [self successResponse:response callback:success];
            
            if ([self isDebug]) {
              [self logWithSuccessResponse:response
                                       url:absolute
                                    params:params];
            }
          }
        } else {
          [self handleCallbackWithError:error fail:fail];
          
          if ([self isDebug]) {
            [self logWithFailError:error url:absolute params:params];
          }
        }
      } else {
        [self handleCallbackWithError:error fail:fail];
        
        if ([self isDebug]) {
          [self logWithFailError:error url:absolute params:params];
        }
      }
    }];
  }
  
  if (session) {
    [[self allTasks] addObject:session];
  }
  
  return session;
}

+ (HYBURLSessionTask *)uploadFileWithUrl:(NSString *)url
                           uploadingFile:(NSString *)uploadingFile
                                progress:(HYBUploadProgress)progress
                                 success:(HYBResponseSuccess)success
                                    fail:(HYBResponseFail)fail {
  if ([NSURL URLWithString:uploadingFile] == nil) {
    HYBAppLog(@"uploadingFile無效,沒法生成URL。請檢查待上傳文件是否存在");
    return nil;
  }
  
  NSURL *uploadURL = nil;
  if ([self baseUrl] == nil) {
    uploadURL = [NSURL URLWithString:url];
  } else {
    uploadURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", [self baseUrl], url]];
  }
  
  if (uploadURL == nil) {
    HYBAppLog(@"URLString無效,沒法生成URL。多是URL中有中文或特殊字符,請嘗試Encode URL");
    return nil;
  }
  
  AFHTTPSessionManager *manager = [self manager];
  NSURLRequest *request = [NSURLRequest requestWithURL:uploadURL];
  HYBURLSessionTask *session = nil;
  
  [manager uploadTaskWithRequest:request fromFile:[NSURL URLWithString:uploadingFile] progress:^(NSProgress * _Nonnull uploadProgress) {
    if (progress) {
      progress(uploadProgress.completedUnitCount, uploadProgress.totalUnitCount);
    }
  } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
    [[self allTasks] removeObject:session];
    
    [self successResponse:responseObject callback:success];
    
    if (error) {
      [self handleCallbackWithError:error fail:fail];
      
      if ([self isDebug]) {
        [self logWithFailError:error url:response.URL.absoluteString params:nil];
      }
    } else {
      if ([self isDebug]) {
        [self logWithSuccessResponse:responseObject
                                 url:response.URL.absoluteString
                              params:nil];
      }
    }
  }];
  
  if (session) {
    [[self allTasks] addObject:session];
  }
  
  return session;
}

+ (HYBURLSessionTask *)uploadWithImage:(UIImage *)image
                                   url:(NSString *)url
                              filename:(NSString *)filename
                                  name:(NSString *)name
                              mimeType:(NSString *)mimeType
                            parameters:(NSDictionary *)parameters
                              progress:(HYBUploadProgress)progress
                               success:(HYBResponseSuccess)success
                                  fail:(HYBResponseFail)fail {
  if ([self baseUrl] == nil) {
    if ([NSURL URLWithString:url] == nil) {
      HYBAppLog(@"URLString無效,沒法生成URL。多是URL中有中文,請嘗試Encode URL");
      return nil;
    }
  } else {
    if ([NSURL URLWithString:[NSString stringWithFormat:@"%@%@", [self baseUrl], url]] == nil) {
      HYBAppLog(@"URLString無效,沒法生成URL。多是URL中有中文,請嘗試Encode URL");
      return nil;
    }
  }
  
  if ([self shouldEncode]) {
    url = [self encodeUrl:url];
  }
  
  NSString *absolute = [self absoluteUrlWithPath:url];
  
  AFHTTPSessionManager *manager = [self manager];
  HYBURLSessionTask *session = [manager POST:url parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
    NSData *imageData = UIImageJPEGRepresentation(image, 1);
    
    NSString *imageFileName = filename;
    if (filename == nil || ![filename isKindOfClass:[NSString class]] || filename.length == 0) {
      NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
      formatter.dateFormat = @"yyyyMMddHHmmss";
      NSString *str = [formatter stringFromDate:[NSDate date]];
      imageFileName = [NSString stringWithFormat:@"%@.jpg", str];
    }
    
    // 上傳圖片,以文件流的格式
    [formData appendPartWithFileData:imageData name:name fileName:imageFileName mimeType:mimeType];
  } progress:^(NSProgress * _Nonnull uploadProgress) {
    if (progress) {
      progress(uploadProgress.completedUnitCount, uploadProgress.totalUnitCount);
    }
  } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    [[self allTasks] removeObject:task];
    [self successResponse:responseObject callback:success];
    
    if ([self isDebug]) {
      [self logWithSuccessResponse:responseObject
                               url:absolute
                            params:parameters];
    }
  } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    [[self allTasks] removeObject:task];
    
    [self handleCallbackWithError:error fail:fail];
    
    if ([self isDebug]) {
      [self logWithFailError:error url:absolute params:nil];
    }
  }];
  
  [session resume];
  if (session) {
    [[self allTasks] addObject:session];
  }
  
  return session;
}

+ (HYBURLSessionTask *)downloadWithUrl:(NSString *)url
                            saveToPath:(NSString *)saveToPath
                              progress:(HYBDownloadProgress)progressBlock
                               success:(HYBResponseSuccess)success
                               failure:(HYBResponseFail)failure {
  if ([self baseUrl] == nil) {
    if ([NSURL URLWithString:url] == nil) {
      HYBAppLog(@"URLString無效,沒法生成URL。多是URL中有中文,請嘗試Encode URL");
      return nil;
    }
  } else {
    if ([NSURL URLWithString:[NSString stringWithFormat:@"%@%@", [self baseUrl], url]] == nil) {
      HYBAppLog(@"URLString無效,沒法生成URL。多是URL中有中文,請嘗試Encode URL");
      return nil;
    }
  }
  
  NSURLRequest *downloadRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
  AFHTTPSessionManager *manager = [self manager];
  
  HYBURLSessionTask *session = nil;
  
  session = [manager downloadTaskWithRequest:downloadRequest progress:^(NSProgress * _Nonnull downloadProgress) {
    if (progressBlock) {
      progressBlock(downloadProgress.completedUnitCount, downloadProgress.totalUnitCount);
    }
  } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
    return [NSURL fileURLWithPath:saveToPath];
  } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
    [[self allTasks] removeObject:session];
    
    if (error == nil) {
      if (success) {
        success(filePath.absoluteString);
      }
      
      if ([self isDebug]) {
        HYBAppLog(@"Download success for url %@",
                  [self absoluteUrlWithPath:url]);
      }
    } else {
      [self handleCallbackWithError:error fail:failure];
      
      if ([self isDebug]) {
        HYBAppLog(@"Download fail for url %@, reason : %@",
                  [self absoluteUrlWithPath:url],
                  [error description]);
      }
    }
  }];
  
  [session resume];
  if (session) {
    [[self allTasks] addObject:session];
  }
  
  return session;
}

#pragma mark - Private
+ (AFHTTPSessionManager *)manager {
  @synchronized (self) {
    // 只要不切換baseurl,就一直使用同一個session manager
    if (sg_sharedManager == nil || sg_isBaseURLChanged) {
      // 開啓轉圈圈
      [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
      
      AFHTTPSessionManager *manager = nil;;
      if ([self baseUrl] != nil) {
    #warning session 容易形成循環引用 delegate 是強引用類型 解決方法:1.經過單例的方式建立 2.delloc中釋放delegate manager
= [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:[self baseUrl]]]; } else { manager = [AFHTTPSessionManager manager]; } switch (sg_requestType) { case kHYBRequestTypeJSON: { manager.requestSerializer = [AFJSONRequestSerializer serializer]; break; } case kHYBRequestTypePlainText: { manager.requestSerializer = [AFHTTPRequestSerializer serializer]; break; } default: { break; } } switch (sg_responseType) { case kHYBResponseTypeJSON: { manager.responseSerializer = [AFJSONResponseSerializer serializer]; break; } case kHYBResponseTypeXML: { manager.responseSerializer = [AFXMLParserResponseSerializer serializer]; break; } case kHYBResponseTypeData: { manager.responseSerializer = [AFHTTPResponseSerializer serializer]; break; } default: { break; } } manager.requestSerializer.stringEncoding = NSUTF8StringEncoding; for (NSString *key in sg_httpHeaders.allKeys) { if (sg_httpHeaders[key] != nil) { [manager.requestSerializer setValue:sg_httpHeaders[key] forHTTPHeaderField:key]; } } manager.responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[@"application/json", @"text/html", @"text/json", @"text/plain", @"text/javascript", @"text/xml", @"image/*"]]; manager.requestSerializer.timeoutInterval = sg_timeout; // 設置容許同時最大併發數量,過大容易出問題 manager.operationQueue.maxConcurrentOperationCount = 3; sg_sharedManager = manager; } } return sg_sharedManager; } + (void)detectNetwork { AFNetworkReachabilityManager *reachabilityManager = [AFNetworkReachabilityManager sharedManager]; [reachabilityManager startMonitoring]; [reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { if (status == AFNetworkReachabilityStatusNotReachable){ sg_networkStatus = kHYBNetworkStatusNotReachable; } else if (status == AFNetworkReachabilityStatusUnknown){ sg_networkStatus = kHYBNetworkStatusUnknown; } else if (status == AFNetworkReachabilityStatusReachableViaWWAN){ sg_networkStatus = kHYBNetworkStatusReachableViaWWAN; } else if (status == AFNetworkReachabilityStatusReachableViaWiFi){ sg_networkStatus = kHYBNetworkStatusReachableViaWiFi; } }]; } + (void)logWithSuccessResponse:(id)response url:(NSString *)url params:(NSDictionary *)params { HYBAppLog(@"\n"); HYBAppLog(@"\nRequest success, URL: %@\n params:%@\n response:%@\n\n", [self generateGETAbsoluteURL:url params:params], params, [self tryToParseData:response]); } + (void)logWithFailError:(NSError *)error url:(NSString *)url params:(id)params { NSString *format = @" params: "; if (params == nil || ![params isKindOfClass:[NSDictionary class]]) { format = @""; params = @""; } HYBAppLog(@"\n"); if ([error code] == NSURLErrorCancelled) { HYBAppLog(@"\nRequest was canceled mannully, URL: %@ %@%@\n\n", [self generateGETAbsoluteURL:url params:params], format, params); } else { HYBAppLog(@"\nRequest error, URL: %@ %@%@\n errorInfos:%@\n\n", [self generateGETAbsoluteURL:url params:params], format, params, [error localizedDescription]); } } // 僅對一級字典結構起做用 + (NSString *)generateGETAbsoluteURL:(NSString *)url params:(id)params { if (params == nil || ![params isKindOfClass:[NSDictionary class]] || [params count] == 0) { return url; } NSString *queries = @""; for (NSString *key in params) { id value = [params objectForKey:key]; if ([value isKindOfClass:[NSDictionary class]]) { continue; } else if ([value isKindOfClass:[NSArray class]]) { continue; } else if ([value isKindOfClass:[NSSet class]]) { continue; } else { queries = [NSString stringWithFormat:@"%@%@=%@&", (queries.length == 0 ? @"&" : queries), key, value]; } } if (queries.length > 1) { queries = [queries substringToIndex:queries.length - 1]; } if (([url hasPrefix:@"http://"] || [url hasPrefix:@"https://"]) && queries.length > 1) { if ([url rangeOfString:@"?"].location != NSNotFound || [url rangeOfString:@"#"].location != NSNotFound) { url = [NSString stringWithFormat:@"%@%@", url, queries]; } else { queries = [queries substringFromIndex:1]; url = [NSString stringWithFormat:@"%@?%@", url, queries]; } } return url.length == 0 ? queries : url; } + (NSString *)encodeUrl:(NSString *)url { return [self hyb_URLEncode:url]; } + (id)tryToParseData:(id)responseData { if ([responseData isKindOfClass:[NSData class]]) { // 嘗試解析成JSON if (responseData == nil) { return responseData; } else { NSError *error = nil; NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&error]; if (error != nil) { return responseData; } else { return response; } } } else { return responseData; } } + (void)successResponse:(id)responseData callback:(HYBResponseSuccess)success { if (success) { success([self tryToParseData:responseData]); } } + (NSString *)hyb_URLEncode:(NSString *)url { return [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; // 採用下面的方式反而不能請求成功 // NSString *newString = // CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, // (CFStringRef)url, // NULL, // CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding))); // if (newString) { // return newString; // } // // return url; } + (id)cahceResponseWithURL:(NSString *)url parameters:params { id cacheData = nil; if (url) { // Try to get datas from disk NSString *directoryPath = cachePath(); NSString *absoluteURL = [self generateGETAbsoluteURL:url params:params]; NSString *key = [NSString hybnetworking_md5:absoluteURL]; NSString *path = [directoryPath stringByAppendingPathComponent:key]; NSData *data = [[NSFileManager defaultManager] contentsAtPath:path]; if (data) { cacheData = data; HYBAppLog(@"Read data from cache for url: %@\n", url); } } return cacheData; } + (void)cacheResponseObject:(id)responseObject request:(NSURLRequest *)request parameters:params { if (request && responseObject && ![responseObject isKindOfClass:[NSNull class]]) { NSString *directoryPath = cachePath(); NSError *error = nil; if (![[NSFileManager defaultManager] fileExistsAtPath:directoryPath isDirectory:nil]) { [[NSFileManager defaultManager] createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:&error]; if (error) { HYBAppLog(@"create cache dir error: %@\n", error); return; } } NSString *absoluteURL = [self generateGETAbsoluteURL:request.URL.absoluteString params:params]; NSString *key = [NSString hybnetworking_md5:absoluteURL]; NSString *path = [directoryPath stringByAppendingPathComponent:key]; NSDictionary *dict = (NSDictionary *)responseObject; NSData *data = nil; if ([dict isKindOfClass:[NSData class]]) { data = responseObject; } else { data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error]; } if (data && error == nil) { BOOL isOk = [[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil]; if (isOk) { HYBAppLog(@"cache file ok for request: %@\n", absoluteURL); } else { HYBAppLog(@"cache file error for request: %@\n", absoluteURL); } } } } + (NSString *)absoluteUrlWithPath:(NSString *)path { if (path == nil || path.length == 0) { return @""; } if ([self baseUrl] == nil || [[self baseUrl] length] == 0) { return path; } NSString *absoluteUrl = path; if (![path hasPrefix:@"http://"] && ![path hasPrefix:@"https://"]) { if ([[self baseUrl] hasSuffix:@"/"]) { if ([path hasPrefix:@"/"]) { NSMutableString * mutablePath = [NSMutableString stringWithString:path]; [mutablePath deleteCharactersInRange:NSMakeRange(0, 1)]; absoluteUrl = [NSString stringWithFormat:@"%@%@", [self baseUrl], mutablePath]; } else { absoluteUrl = [NSString stringWithFormat:@"%@%@",[self baseUrl], path]; } } else { if ([path hasPrefix:@"/"]) { absoluteUrl = [NSString stringWithFormat:@"%@%@",[self baseUrl], path]; } else { absoluteUrl = [NSString stringWithFormat:@"%@/%@", [self baseUrl], path]; } } } return absoluteUrl; } + (void)handleCallbackWithError:(NSError *)error fail:(HYBResponseFail)fail { if ([error code] == NSURLErrorCancelled) { if (sg_shouldCallbackOnCancelRequest) { if (fail) { fail(error); } } } else { if (fail) { fail(error); } } } @end

 

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

// 項目打包上線都不會打印日誌,所以可放心。
#ifdef DEBUG
#define HYBAppLog(s, ... ) NSLog( @"[%@ in line %d] ===============>%@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define HYBAppLog(s, ... )
#endif

/*!
 *  @author 黃, 16-01-08 14:01:26
 *
 *  下載進度
 *
 *  @param bytesRead                 已下載的大小
 *  @param totalBytesRead            文件總大小
 *  @param totalBytesExpectedToRead 還有多少須要下載
 */
typedef void (^HYBDownloadProgress)(int64_t bytesRead,
                                    int64_t totalBytesRead);

typedef HYBDownloadProgress HYBGetProgress;
typedef HYBDownloadProgress HYBPostProgress;

/*!
 *  @author 黃, 16-01-08 14:01:26
 *
 *  上傳進度
 *
 *  @param bytesWritten              已上傳的大小
 *  @param totalBytesWritten         總上傳大小
 */
typedef void (^HYBUploadProgress)(int64_t bytesWritten,
                                  int64_t totalBytesWritten);

typedef NS_ENUM(NSUInteger, HYBResponseType) {
  kHYBResponseTypeJSON = 1, // 默認
  kHYBResponseTypeXML  = 2, // XML
  // 特殊狀況下,一轉換服務器就沒法識別的,默認會嘗試轉換成JSON,若失敗則須要本身去轉換
  kHYBResponseTypeData = 3
};

typedef NS_ENUM(NSUInteger, HYBRequestType) {
  kHYBRequestTypeJSON = 1, // 默認
  kHYBRequestTypePlainText  = 2 // 普通text/html
};

typedef NS_ENUM(NSInteger, HYBNetworkStatus) {
    kHYBNetworkStatusUnknown          = -1,//未知網絡
    kHYBNetworkStatusNotReachable     = 0,//網絡無鏈接
    kHYBNetworkStatusReachableViaWWAN = 1,//2,3,4G網絡
    kHYBNetworkStatusReachableViaWiFi = 2,//WIFI網絡
};

@class NSURLSessionTask;

// 請勿直接使用NSURLSessionDataTask,以減小對第三方的依賴
// 全部接口返回的類型都是基類NSURLSessionTask,若要接收返回值
// 且處理,請轉換成對應的子類類型
typedef NSURLSessionTask HYBURLSessionTask;
typedef void(^HYBResponseSuccess)(id response);
typedef void(^HYBResponseFail)(NSError *error);

/*!
 *  @author huangyibiao, 15-11-15 13:11:31
 *
 *  基於AFNetworking的網絡層封裝類.
 *
 *  @note 這裏只提供公共api
 */
@interface HYBNetworking : NSObject

/*!
 *  @author 黃, 15-11-15 13:11:45
 *
 *  用於指定網絡請求接口的基礎url,如:
 *  http://henishuo.com或者http://101.200.209.244
 *  一般在AppDelegate中啓動時就設置一次就能夠了。若是接口有來源
 *  於多個服務器,能夠調用更新
 *
 *  @param baseUrl 網絡接口的基礎url
 */
+ (void)updateBaseUrl:(NSString *)baseUrl;
+ (NSString *)baseUrl;

/**
 *    設置請求超時時間,默認爲60秒
 *
 *    @param timeout 超時時間
 */
+ (void)setTimeout:(NSTimeInterval)timeout;

/**
 *    當檢查到網絡異常時,是否從從本地提取數據。默認爲NO。一旦設置爲YES,當設置刷新緩存時,
 *  若網絡異常也會從緩存中讀取數據。一樣,若是設置超時不回調,一樣也會在網絡異常時回調,除非
 *  本地沒有數據!
 *
 *    @param shouldObtain    YES/NO
 */
+ (void)obtainDataFromLocalWhenNetworkUnconnected:(BOOL)shouldObtain;

/**
 *    @author 黃
 *
 *    默認只緩存GET請求的數據,對於POST請求是不緩存的。若是要緩存POST獲取的數據,須要手動調用設置
 *  對JSON類型數據有效,對於PLIST、XML不肯定!
 *
 *    @param isCacheGet            默認爲YES
 *    @param shouldCachePost    默認爲NO
 */
+ (void)cacheGetRequest:(BOOL)isCacheGet shoulCachePost:(BOOL)shouldCachePost;

/**
 *    @author 黃
 *
 *    獲取緩存總大小/bytes
 *
 *    @return 緩存大小
 */
+ (unsigned long long)totalCacheSize;

/**
 *    默認不會自動清除緩存,若是須要,能夠設置自動清除緩存,而且須要指定上限。當指定上限>0M時,
 *  若緩存達到了上限值,則每次啓動應用則嘗試自動去清理緩存。
 *
 *    @param mSize                緩存上限大小,單位爲M(兆),默認爲0,表示不清理
 */
+ (void)autoToClearCacheWithLimitedToSize:(NSUInteger)mSize;

/**
 *    @author 黃
 *
 *    清除緩存
 */
+ (void)clearCaches;

/*!
 *  @author 黃, 15-11-15 14:11:40
 *
 *  開啓或關閉接口打印信息
 *
 *  @param isDebug 開發期,最好打開,默認是NO
 */
+ (void)enableInterfaceDebug:(BOOL)isDebug;

/*!
 *  @author 黃, 15-12-25 15:12:45
 *
 *  配置請求格式,默認爲JSON。若是要求傳XML或者PLIST,請在全局配置一下
 *
 *  @param requestType 請求格式,默認爲JSON
 *  @param responseType 響應格式,默認爲JSO,
 *  @param shouldAutoEncode YES or NO,默認爲NO,是否自動encode url
 *  @param shouldCallbackOnCancelRequest 當取消請求時,是否要回調,默認爲YES
 */
+ (void)configRequestType:(HYBRequestType)requestType
             responseType:(HYBResponseType)responseType
      shouldAutoEncodeUrl:(BOOL)shouldAutoEncode
  callbackOnCancelRequest:(BOOL)shouldCallbackOnCancelRequest;

/*!
 *  @author 黃, 15-11-16 13:11:41
 *
 *  配置公共的請求頭,只調用一次便可,一般放在應用啓動的時候配置就能夠了
 *
 *  @param httpHeaders 只須要將與服務器商定的固定參數設置便可
 */
+ (void)configCommonHttpHeaders:(NSDictionary *)httpHeaders;

/**
 *    @author 黃
 *
 *    取消全部請求
 */
+ (void)cancelAllRequest;
/**
 *    @author 黃
 *
 *    取消某個請求。若是是要取消某個請求,最好是引用接口所返回來的HYBURLSessionTask對象,
 *  而後調用對象的cancel方法。若是不想引用對象,這裏額外提供了一種方法來實現取消某個請求
 *
 *    @param url                URL,能夠是絕對URL,也能夠是path(也就是不包括baseurl)
 */
+ (void)cancelRequestWithURL:(NSString *)url;

/*!
 *  @author 黃, 15-11-15 13:11:50
 *
 *  GET請求接口,若不指定baseurl,可傳完整的url
 *
 *  @param url     接口路徑,如/path/getArticleList
 *  @param refreshCache 是否刷新緩存。因爲請求成功也可能沒有數據,對於業務失敗,只能經過人爲手動判斷
 *  @param params  接口中所須要的拼接參數,如@{"categoryid" : @(12)}
 *  @param success 接口成功請求到數據的回調
 *  @param fail    接口請求數據失敗的回調
 *
 *  @return 返回的對象中有可取消請求的API
 */
+ (HYBURLSessionTask *)getWithUrl:(NSString *)url
                     refreshCache:(BOOL)refreshCache
                          success:(HYBResponseSuccess)success
                             fail:(HYBResponseFail)fail;
// 多一個params參數
+ (HYBURLSessionTask *)getWithUrl:(NSString *)url
                     refreshCache:(BOOL)refreshCache
                           params:(NSDictionary *)params
                          success:(HYBResponseSuccess)success
                             fail:(HYBResponseFail)fail;
// 多一個帶進度回調
+ (HYBURLSessionTask *)getWithUrl:(NSString *)url
                     refreshCache:(BOOL)refreshCache
                           params:(NSDictionary *)params
                         progress:(HYBGetProgress)progress
                          success:(HYBResponseSuccess)success
                             fail:(HYBResponseFail)fail;

/*!
 *  @author 黃, 15-11-15 13:11:50
 *
 *  POST請求接口,若不指定baseurl,可傳完整的url
 *
 *  @param url     接口路徑,如/path/getArticleList
 *  @param params  接口中所需的參數,如@{"categoryid" : @(12)}
 *  @param success 接口成功請求到數據的回調
 *  @param fail    接口請求數據失敗的回調
 *
 *  @return 返回的對象中有可取消請求的API
 */
+ (HYBURLSessionTask *)postWithUrl:(NSString *)url
                      refreshCache:(BOOL)refreshCache
                            params:(NSDictionary *)params
                           success:(HYBResponseSuccess)success
                              fail:(HYBResponseFail)fail;
+ (HYBURLSessionTask *)postWithUrl:(NSString *)url
                      refreshCache:(BOOL)refreshCache
                            params:(NSDictionary *)params
                          progress:(HYBPostProgress)progress
                           success:(HYBResponseSuccess)success
                              fail:(HYBResponseFail)fail;
/**
 *    @author 黃, 16-01-31 00:01:40
 *
 *    圖片上傳接口,若不指定baseurl,可傳完整的url
 *
 *    @param image            圖片對象
 *    @param url                上傳圖片的接口路徑,如/path/images/
 *    @param filename        給圖片起一個名字,默認爲當前日期時間,格式爲"yyyyMMddHHmmss",後綴爲`jpg`
 *    @param name                與指定的圖片相關聯的名稱,這是由後端寫接口的人指定的,如imagefiles
 *    @param mimeType        默認爲image/jpeg
 *    @param parameters    參數
 *    @param progress        上傳進度
 *    @param success        上傳成功回調
 *    @param fail                上傳失敗回調
 *
 *    @return
 */
+ (HYBURLSessionTask *)uploadWithImage:(UIImage *)image
                                   url:(NSString *)url
                              filename:(NSString *)filename
                                  name:(NSString *)name
                              mimeType:(NSString *)mimeType
                            parameters:(NSDictionary *)parameters
                              progress:(HYBUploadProgress)progress
                               success:(HYBResponseSuccess)success
                                  fail:(HYBResponseFail)fail;

/**
 *    @author 黃, 16-01-31 00:01:59
 *
 *    上傳文件操做
 *
 *    @param url                        上傳路徑
 *    @param uploadingFile    待上傳文件的路徑
 *    @param progress            上傳進度
 *    @param success                上傳成功回調
 *    @param fail                    上傳失敗回調
 *
 *    @return
 */
+ (HYBURLSessionTask *)uploadFileWithUrl:(NSString *)url
                           uploadingFile:(NSString *)uploadingFile
                                progress:(HYBUploadProgress)progress
                                 success:(HYBResponseSuccess)success
                                    fail:(HYBResponseFail)fail;


/*!
 *  @author 黃, 16-01-08 15:01:11
 *
 *  下載文件
 *
 *  @param url           下載URL
 *  @param saveToPath    下載到哪一個路徑下
 *  @param progressBlock 下載進度
 *  @param success       下載成功後的回調
 *  @param failure       下載失敗後的回調
 */
+ (HYBURLSessionTask *)downloadWithUrl:(NSString *)url
                            saveToPath:(NSString *)saveToPath
                              progress:(HYBDownloadProgress)progressBlock
                               success:(HYBResponseSuccess)success
                               failure:(HYBResponseFail)failure;

@end

 

使用:json

  // 一般放在appdelegate就能夠了
  [HYBNetworking updateBaseUrl:@"http://apistore.baidu.com"];
  [HYBNetworking enableInterfaceDebug:YES];
  
  // 配置請求和響應類型,因爲部分夥伴們的服務器不接收JSON傳過去,如今默認值改爲了plainText
  [HYBNetworking configRequestType:kHYBRequestTypePlainText
                      responseType:kHYBResponseTypeJSON
               shouldAutoEncodeUrl:YES
           callbackOnCancelRequest:NO];
  
  /*
   [HYBNetworking.m:in line: 189]-->[message:
   absoluteUrl: http://apistore.baidu.com/microservice/cityinfo?cityname=%E5%8C%97%E4%BA%AC
   params:(null)
   response:{
   errNum = 0;
   retData =     {
   cityCode = 101010100;
   cityName = "\U5317\U4eac";
   provinceName = "\U5317\U4eac";
   telAreaCode = 010;
   zipCode = 100000;
   };
   retMsg = success;
   }
   ]
   */
  
  // 設置GET、POST請求都緩存
  [HYBNetworking cacheGetRequest:YES shoulCachePost:YES];
  
  // 測試GET API
  NSString *url = @"http://api.map.baidu.com/telematics/v3/weather?location=嘉興&output=json&ak=5slgyqGDENN7Sy7pw29IUvrZ";
  //   設置請求類型爲text/html類型
  //  [HYBNetworking configRequestType:kHYBRequestTypePlainText];
  //  [HYBNetworking configResponseType:kHYBResponseTypeData];
  // 若是請求回來的數據是業務數據,可是是失敗的,這時候須要外部開發人員才能判斷是業務失敗。
  // 內部處理是隻有走failure的才能判斷爲無效數據,纔不會緩存
  // 若是設置爲YES,則每次會去刷新緩存,也就是不會讀取緩存,即便已經緩存起來
  // 新下載的數據會從新緩存起來
  [HYBNetworking getWithUrl:url refreshCache:NO params:nil progress:^(int64_t bytesRead, int64_t totalBytesRead) {
    NSLog(@"progress: %f, cur: %lld, total: %lld",
          (bytesRead * 1.0) / totalBytesRead,
          bytesRead,
          totalBytesRead);
  } success:^(id response) {
    
  } fail:^(NSError *error) {
    
  }];
  
  
  // 測試POST API:
  // 假數據
  NSDictionary *postDict = @{ @"urls": @"http://www.henishuo.com/git-use-inwork/",
                              @"goal" : @"site",
                              @"total" : @(123)
                              };
  NSString *path = @"/urls?site=www.henishuo.com&token=bRidefmXoNxIi3Jp";
  // 因爲這裏有兩套基礎路徑,用時就須要更新
  [HYBNetworking updateBaseUrl:@"http://data.zz.baidu.com"];
  // 每次刷新緩存
  // 若是獲取到的業務數據是不正確的,則須要下次調用時設置爲YES,表示要刷新緩存
// HYBURLSessionTask *task =
  [HYBNetworking postWithUrl:path refreshCache:YES params:postDict success:^(id response) {
    
  } fail:^(NSError *error) {
    
  }];
  
  // 取消所有請求
//  [HYBNetworking cancelAllRequest];
  
  // 取消單個請求方法一
//  [HYBNetworking cancelRequestWithURL:path];
  
  // 取消單個請求方法二
//  [task cancel];
  
  NSLog(@"%lld", [HYBNetworking totalCacheSize]);
//  [HYBNetworking clearCaches];
  
   path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/b.zip"];
[HYBNetworking downloadWithUrl:@"http://wiki.lbsyun.baidu.com/cms/iossdk/sdk/BaiduMap_IOSSDK_v2.10.2_All.zip" saveToPath:path progress:^(int64_t bytesRead, int64_t totalBytesRead) {
    
  } success:^(id response) {
    
  } failure:^(NSError *error) {
    
  }];
//  NSLog(@"%@", task);
}
相關文章
相關標籤/搜索