afn取消所有网络请求 ios
2017-11-16 16:10:00 weixin_34272308 阅读数 56

第一点:不要initialize a new AFHTTPSessionManager object everytime 一定要把manager用成全局的
第二点:把请求返回的task对象丢进数组,下次触发的时候把遍历数组,把之前的所有任务[task cancel]

// somewhere in your class, let's say in ViewDidLoad you should init the AFHTTPSessionManager object  
- (void)viewDidLoad {  
    [super viewDidLoad];  
  
    /// create the AFHTTPSessionManager object, we're gonna use it in every request  
    self.manager = [[AFHTTPSessionManager alloc] init];  
    self.manager.responseSerializer = [AFJSONResponseSerializer serializer];  
  
    /// create an array that is going to hold the requests task we've sent to the server. so we can get back to them later  
    self.arrayOfTasks = [NSMutableArray new];  
    /// discussion:  
    /// an array holds multiple objects. if you just want to hold a ref to the latest task object  
    /// then create a property of NSURLSessionDataTask instead of NSMutableArray, and let it point to the latest NSURLSessionDataTask object you create  
  
}  
  
  
  
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;{  
    /// your code goes here  
    /// .....  
    /// .....  
    /// .....  
    /// .....  
    /// till we reach  
    if(stringLength>=3){  
        /// cancel all previous tasks  
        [self.arrayOfTasks enumerateObjectsUsingBlock:^(NSURLSessionDataTask *taskObj, NSUInteger idx, BOOLBOOL *stop) {  
            [taskObj cancel]; /// when sending cancel to the task failure: block is going to be called  
        }];  
  
        /// empty the arraOfTasks  
        [self.arrayOfTasks removeAllObjects];  
  
        /// init new task  
        NSURLSessionDataTask *task = [self.manager GET:urlString parameters:nil success:^(NSURLSessionDataTask *task, id responseObject){  
           /// your code  
        }failure:^(NSURLSessionDataTask *task, NSError *error){  
           /// your code  
        }];  
  
        /// add the task to our arrayOfTasks  
        [self.arrayOfTasks addObject:task];  
    }  
    return YES;  
}  

注意:
这里的task cancel亲测确实能把网络请求cancel掉,可以看下面的log,记住一点,这里cancel之后不代表就不回调
了,只是会回调到error的那个block里面,各位需要信息的可以测试下,在error打个断点就能调试出来了

参考文章链接:http://blog.csdn.net/deft_mkjing/article/details/51985232

2017-03-14 16:41:00 weixin_33813128 阅读数 16

项目地址:https://github.com/purejf/BaseRequest

AFNetWorking->CYRequestManager->CYBaseRequest

封装了一下网络请求,牵扯到三个类

1. AFNetworking
2. CYRequestManager
3. CYBaseRequest
设计思路
  1. 先封装一下AFNetworking,即CYRequestManager
  2. 但是CYRequestManager需要参数、链接,参数和链接还是过于暴露,所以设计CYBaseRequest类
  3. 使用时继承CYBaseRequest,将类的属性作为参数(模型转JSON),将属性转化为字典参数,发送请求,即可
  4. 简单封装,以后逐步完善
用例1

直接使用CYBaseRequest

    // 1. 创建请求
    CYBaseRequest *request = [CYBaseRequest new];
    request.url = @"www.baidu.com";
    
    // 2. 发送请求
    [request sendRequestWithCompletionHandle:^(BOOL success, id response, NSString *message) {
        
    }];
}
用例2

创建一个CYUserInfoRequest继承自CYBaseRequest

CYUserInfoRequest.h

@interface CYUserInfoRequest : CYBaseRequest

@property (nonatomic, assign) NSInteger userId;

@end

CYUserInfoRequest.m

@implementation CYUserInfoRequest

- (instancetype)init {
    self = [super init];
    if (self) {
        self.url = @"请求需要的链接";
    }
    return self;
}

@end

如何使用?

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 1. 创建请求
    CYUserInfoRequest *userInfoR = [CYUserInfoRequest new];
    userInfoR.userId = 1;
    // 在.m中可以设置
    // userInfoR.url = @"www.baidu.com";
    // 可选
    // userInfoR.extraParams = @{
    //                              @"username" : @"xxx"
    //                              };
    
    // 2. 设置请求方式
    userInfoR.methodType = CYRequestMethodTypePOST;
    
    // 3. 发送请求
    [userInfoR sendRequestWithCompletionHandle:^(BOOL success, id response, NSString *message) {
        
    }];
    
}

@end

}
设计代码示例 - CYRequestManager

#import "AFNetworking.h"
#import "CYRequestConstant.h"

// 请求成功回调
typedef void(^CYRequestManagerSuccessHandle)(NSURLSessionTask *task, id response);

// 请求失败回调
typedef void(^CYRequestManagerFailureHandle)(NSURLSessionTask *task, NSError *error);

@interface CYRequestManager : NSObject

/**
 request By NSURLSession
 
 @param URLString 请求链接
 @param params 请求参数
 @param methodType 请求方式
 @param serializerType 数据解析类型
 @param successHandle 请求成功回调
 @param failureHandle 请求失败回调
 */
+ (void)requestWithURLString:(NSString *)URLString
                      params:(NSDictionary *)params
                  methodType:(CYRequestMethodType)methodType
              serializerType:(CYResponseSeializerType)serializerType
               successHandle:(CYRequestManagerSuccessHandle)successHandle
               failureHandle:(CYRequestManagerFailureHandle)failureHandle;

/**
 a multipart `POST` request By NSURLSession
 
 @param URLString 请求链接
 @param params 请求参数
 @param serializerType 数据解析类型
 @param constructingBody 添加请求体
 @param successHandle 请求成功回调
 @param failureHandle 请求失败回调
 */
+ (void)POSTWithURLString:(NSString *)URLString
                   params:(NSDictionary *)params
            serializerType:(CYResponseSeializerType)serializerType
         constructingBody:(void (^)(id<AFMultipartFormData> formData))constructingBody
            successHandle:(CYRequestManagerSuccessHandle)successHandle
            failureHandle:(CYRequestManagerFailureHandle)failureHandle;

@end
#import "CYRequestManager.h"
#import "AFNetworking.h"

@interface AFHTTPSessionManager (Shared)

+ (instancetype)sharedManager;

@end

@implementation AFHTTPSessionManager (Shared)

+ (instancetype)sharedManager {
    static AFHTTPSessionManager *_singleton;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _singleton = [AFHTTPSessionManager manager];
        _singleton.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/plain", @"text/json", @"text/javascript", @"text/html", nil];
    });
    return _singleton;
}

@end

@implementation CYRequestManager

+ (void)requestWithURLString:(NSString *)URLString
                      params:(NSDictionary *)params
                  methodType:(CYRequestMethodType)methodType
              serializerType:(CYResponseSeializerType)serializerType
               successHandle:(CYRequestManagerSuccessHandle)successHandle
               failureHandle:(CYRequestManagerFailureHandle)failureHandle {
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager sharedManager];
    
    manager.responseSerializer = [self responseSearalizerWithSerilizerType:serializerType];
    
    switch (methodType) {
        case CYRequestMethodTypeGET: [manager GET:URLString parameters:params progress:nil success:successHandle failure:failureHandle]; break;
        case CYRequestMethodTypePOST: [manager POST:URLString parameters:params progress:nil success:successHandle failure:failureHandle]; break;
        case CYRequestMethodTypePUT: [manager PUT:URLString parameters:params success:successHandle failure:failureHandle]; break;
        case CYRequestMethodTypePATCH: [manager PATCH:URLString parameters:params success:successHandle failure:failureHandle]; break;
        case CYRequestMethodTypeDELETE: [manager DELETE:URLString parameters:params success:successHandle failure:failureHandle]; break;
        case CYRequestMethodTypeHEAD: [manager HEAD:URLString parameters:params success:^(NSURLSessionDataTask * _Nonnull task) {
            !successHandle ?: successHandle(task, nil);
        } failure:failureHandle]; break;
    }
    
}

+ (void)POSTWithURLString:(NSString *)URLString
                   params:(NSDictionary *)params
           serializerType:(CYResponseSeializerType)serializerType
         constructingBody:(void (^)(id<AFMultipartFormData> formData))constructingBody
            successHandle:(CYRequestManagerSuccessHandle)successHandle
            failureHandle:(CYRequestManagerFailureHandle)failureHandle {
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager sharedManager];
    
    manager.responseSerializer = [self responseSearalizerWithSerilizerType:serializerType];
    
    [manager POST:URLString parameters:params constructingBodyWithBlock:constructingBody progress:nil success:successHandle failure:failureHandle];
}

+ (AFHTTPResponseSerializer *)responseSearalizerWithSerilizerType:(CYResponseSeializerType)serilizerType {
    switch (serilizerType) {
        case CYResponseSeializerTypeDefault: return [AFJSONResponseSerializer serializer]; break;
        case CYResponseSeializerTypeJSON: return [AFJSONResponseSerializer serializer]; break;
        case CYResponseSeializerTypeXML: return [AFXMLParserResponseSerializer serializer]; break;
        case CYResponseSeializerTypePlist: return [AFPropertyListResponseSerializer serializer]; break;
        case CYResponseSeializerTypeCompound: return [AFCompoundResponseSerializer serializer]; break;
        case CYResponseSeializerTypeImage: return [AFImageResponseSerializer serializer]; break;
        case CYResponseSeializerTypeData: return [AFHTTPResponseSerializer serializer]; break;
        default: return [AFJSONResponseSerializer serializer]; break;
    }
}

@end

设计代码示例 - CYBaseRequest
#import "CYRequestConstant.h"

typedef void(^CYBaseRequestCompletionHandle)(BOOL success, id response, NSString *message);

@interface CYBaseRequest : NSObject

@property (nonatomic, copy) NSString *url;

@property (nonatomic, assign) CYRequestMethodType methodType;

@property (nonatomic, strong) NSDictionary *extraParams;

- (void)sendRequestWithCompletionHandle:(CYBaseRequestCompletionHandle)completionHandle;

@end

#import "CYBaseRequest.h"
#import "YYModel.h"
#import "CYRequestManager.h"

@implementation CYBaseRequest

- (void)sendRequestWithCompletionHandle:(CYBaseRequestCompletionHandle)completionHandle {
    if (!_url || !_url.length) return;
    [CYRequestManager requestWithURLString:_url
                                    params:[self params]
                                methodType:self.methodType
                            serializerType:CYResponseSeializerTypeJSON
                             successHandle:^(NSURLSessionTask *task, id response) {
                                 !completionHandle ?: completionHandle(YES, response, nil);
                             } failureHandle:^(NSURLSessionTask *task, NSError *error) {
                                 !completionHandle ?: completionHandle(NO, nil, error.description);
                             }];
}

- (NSDictionary *)params {
    NSDictionary *json = self.yy_modelToJSONObject;
    if ([json isKindOfClass:[NSDictionary class]]) {
        NSMutableDictionary *params = [(NSDictionary *)json mutableCopy];
        [params addEntriesFromDictionary:self.extraParams];
        for (NSString *delKey in @[@"url", @"methodType", @"extraParams"]) {
            if ([params.allKeys containsObject:delKey]) {
                [params removeObjectForKey:delKey];
            }
        }
        for (id key in params.allKeys) {
            id obj = [params objectForKey:key];
            if (!obj || [obj isKindOfClass:[NSNull class]] || obj == (id)kCFNull) {
                [params removeObjectForKey:key];
            }
        }
        return params;
    }
    return self.extraParams;
}
@end

2017-10-27 12:37:00 weixin_33730836 阅读数 37

AFN:网络请求

AFN主要使用在2个场景中

(1):发送网络请求
(2):实时监测网络状态

AFNetworking 2.0 和3.0 的区别
  1. AFNetworking在3.0版本中删除了基于 NSURLConnection API的所有支持。如果你的项目以前使用过这些API,建议您立即升级到基于 NSURLSession 的API的AFNetworking的版本。
  2. AFNetworking 3.0现已完全基于NSURLSession的API,这降低了维护的负担,同时支持苹果增强关于NSURLSession提供的任何额外功能。
  3. 可以结合MBProgressHUD,网络请求时间短的话,就可以不要显示HUD,提高用户体验,另外HUD也可以懒加载,全程只需要一个HUD即可。HUD内部有创建HUD对象时涉及到请求时间的类方法,在这个方法中如果请求时间小于某个值,就返回nil,即不显示HUD。此外AFN还有联网检测功能,每次请求网络之前先检测有没有网络,没有网络则提示用户(涉及到AFN和HUD的组合封装)
  • GET请求和POST请求的区别:
   GET请求:

   请求参数会在浏览器的地址栏中显示,所以不安全;
   请求参数长度限制长度在1K之内;
    GET请求没有请求体,无法通过request.setCharacterEncoding()来设置参数的编码;
    POST请求:

   请求参数不会显示浏览器的地址栏,相对安全;
   请求参数长度没有限制;
  • 实时检测网络状态改变的类
AFNetworkReachabilityManager 实时检测网络状态改变的类

AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];

// 设置网络状态改变之后的操作
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
    
    // status :当前的网络状态.
    //        AFNetworkReachabilityStatusUnknown
    //        AFNetworkReachabilityStatusNotReachable
    //        AFNetworkReachabilityStatusReachableViaWWAN
    //        AFNetworkReachabilityStatusReachableViaWiFi
    
    switch (status) {
        case AFNetworkReachabilityStatusUnknown:
            NSLog(@"未知的网络状态");
            break;
        case AFNetworkReachabilityStatusNotReachable:
            NSLog(@"没有网络");
            break;
        case AFNetworkReachabilityStatusReachableViaWWAN:
            NSLog(@"蜂窝移动网络");
            break;
        case AFNetworkReachabilityStatusReachableViaWiFi:
            NSLog(@"WIFI网络");
            break;
        default:
            break;
    }
}];
// 开始检测网络状态
[manager startMonitoring];
2018-01-11 17:23:00 weixin_33699914 阅读数 39

Demo_gitHub

3239766-8f662dba0418c31e.jpg
图片源于网络

基于AFN的网络请求封装

  • .h文件
#import <Foundation/Foundation.h>

/** 请求类型的枚举 */
typedef NS_ENUM(NSUInteger, SkyHttpRequestType)
{
    /** get请求 */
    SkyHttpRequestTypeGet = 0,
    /** post请求 */
    SkyHttpRequestTypePost
};

/**
 http通讯成功的block

 @param responseObject 返回的数据
 */
typedef void (^SkyHTTPRequestSuccessBlock)(id responseObject);

/**
 http通讯失败后的block

 @param error 返回的错误信息
 */
typedef void (^SkyHTTPRequestFailedBlock)(NSError *error);


//超时时间
extern NSInteger const kAFNetworkingTimeoutInterval;


@interface AFNetworkingManager : NSObject

/**
 *  网络请求的实例方法
 *
 *  @param type         get / post (项目目前只支持这倆中)
 *  @param urlString    请求的地址
 *  @param parameters   请求的参数
 *  @param successBlock 请求成功回调
 *  @param failureBlock 请求失败回调
 */
+ (void)requestWithType:(SkyHttpRequestType)type
              urlString:(NSString *)urlString
             parameters:(NSDictionary *)parameters
           successBlock:(SkyHTTPRequestSuccessBlock)successBlock
           failureBlock:(SkyHTTPRequestFailedBlock)failureBlock;

/**
 取消队列
 */
+(void)cancelDataTask;
@end
  • .m文件
#import "AFNetworkingManager.h"
#import "AFHTTPSessionManager.h"


NSInteger const kAFNetworkingTimeoutInterval = 10;


@implementation AFNetworkingManager

static AFHTTPSessionManager *aManager;
+ (AFHTTPSessionManager *)sharedAFManager
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        aManager = [AFHTTPSessionManager manager];
        //以下三项manager的属性根据需要进行配置
        aManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"text/xml",@"text/json",@"text/plain",@"text/JavaScript",@"application/json",@"image/jpeg",@"image/png",@"application/octet-stream",nil];
        
        aManager.responseSerializer = [AFHTTPResponseSerializer serializer];
        // 设置超时时间
        aManager.requestSerializer.timeoutInterval = kAFNetworkingTimeoutInterval;
    });
    return aManager;
}

+ (void)requestWithType:(SkyHttpRequestType)type
              urlString:(NSString *)urlString
             parameters:(NSDictionary *)parameters
           successBlock:(SkyHTTPRequestSuccessBlock)successBlock
           failureBlock:(SkyHTTPRequestFailedBlock)failureBlock
{
    if (urlString == nil)
    {
        return;
    }
    
    if (@available(iOS 9.0, *)) {
        urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    }else {
        urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    }
    
    
    if (type == SkyHttpRequestTypeGet)
    {
        
        [[self sharedAFManager] GET:urlString parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
            
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            
            if (successBlock)
            {
                successBlock(responseObject);
            }
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            
            if (error.code !=-999) {
                if (failureBlock)
                {
                    failureBlock(error);
                }
            }
            else{
                NSLog(@"取消队列了");
            }
        }];
        
    }
    
    if (type == SkyHttpRequestTypePost)
    {
        
        [[self sharedAFManager] POST:urlString parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
            
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            
            if (successBlock)
            {
                successBlock(responseObject);
            }
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            
            if (error.code !=-999) {
                if (failureBlock)
                {
                    failureBlock(error);
                }
            }
            else{
                NSLog(@"取消队列了");
            }
            
        }];
    }
}

+(void)cancelDataTask
{
    NSMutableArray *dataTasks = [NSMutableArray arrayWithArray:[self sharedAFManager].dataTasks];
    for (NSURLSessionDataTask *taskObj in dataTasks) {
        [taskObj cancel];
    }
}
@end

主要步骤

  • 创建的AFNetworkingManager类继承自NSObject类

  • 请求类型用枚举定义

/** 请求类型的枚举 */
typedef NS_ENUM(NSUInteger, SkyHttpRequestType)
{
    /** get请求 */
    SkyHttpRequestTypeGet = 0,
    /** post请求 */
    SkyHttpRequestTypePost
};
  • 用block回调请求结果
/**
 http通讯成功的block

 @param responseObject 返回的数据
 */
typedef void (^SkyHTTPRequestSuccessBlock)(id responseObject);

/**
 http通讯失败后的block

 @param error 返回的错误信息
 */
typedef void (^SkyHTTPRequestFailedBlock)(NSError *error);
  • 在.m文件中导入#import "AFHTTPSessionManager.h",并获取AFHTTPSessionManager类単例
static AFHTTPSessionManager *aManager;
+ (AFHTTPSessionManager *)sharedAFManager
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        aManager = [AFHTTPSessionManager manager];
        //以下三项manager的属性根据需要进行配置
        aManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"text/xml",@"text/json",@"text/plain",@"text/JavaScript",@"application/json",@"image/jpeg",@"image/png",@"application/octet-stream",nil];
        
        aManager.responseSerializer = [AFHTTPResponseSerializer serializer];
        // 设置超时时间
        aManager.requestSerializer.timeoutInterval = kAFNetworkingTimeoutInterval;
    });
    return aManager;
}
  • failure返回的"error.code == -999"为取消请求队列
            if (error.code !=-999) {
                if (failureBlock)
                {
                    failureBlock(error);
                }
            }
            else{
                NSLog(@"取消队列了");
            }
  • 以上

Demo_gitHub

2016-12-29 16:45:35 jiwu6174 阅读数 372
各位我今天遇到这样的一个问题就是如何取消单个网络请求功能,我用的是afnetwork这个第三方的框架。我查找了一些相关资料,可是都是取消所有请求的方法和建议,我现在想取消单个网络请求,好比我进入A页面后这个时候这个时候它在加载。我在其页面加载的时候点击跳转到B页面,这个时候如果没有做网络取消的话,其实这个A页面的网络请求还是在继续这。我想让它当页面一跳装或者一关闭就取消掉当前网络请求。请问有没有人做个这样的功能
没有更多推荐了,返回首页