美文网首页iOS 开发iOS开发-网络
iOS取消界面的网络请求

iOS取消界面的网络请求

作者: 像风一样的孩子丶 | 来源:发表于2016-07-11 14:40 被阅读3854次

在开发过程中有些界面的接口请求时间较长.如果用户不想等待,退出这个界面,但是界面的请求还在继续,万一网络很弱,请求超时,就算退出那个界面也会弹出超时报错.如果接口数据量大,就会占用很多内存.

所以,要在当前界面退出的时候取消所有的请求.下面与大家分享一下处理方法,有不足之处请小伙伴们帮我指出.谢谢啦~

要取消网络请求,就需要一个类NSURLSessionDataTask的对象方法-cancel.

一:为了方便项目中的使用,建议创建一个ViewController的根类.你的所有VC都可以去继承它.调用父类的方法很方便.下面是VC根类的方法.

#import

#import

@interface BaseViewController :UIViewController

@property(nonatomic,strong)NSURLSessionDataTask*task;

@end

在根类的.h文件中创建一个属性,NSURLSessionDataTask*task,他就是用来取消界面的数据请求的..m文件的话,小伙伴们可以根据自己的喜欢,把常用的方法,比如请求数据使用的Progress添加到里面,要记得要在.h文件声明你的方法哦~

二:首先创建两个控制器.每个控制器上都放一个button.(既然创建根类了,那就这两个VC都继承于上面的BaseViewController吧.)

第一个:

第一个控制器

点击第一个控制器进入第二个控制器,我们在第二个控制器里面进行网络请求.

第二个控制器

点击第二个控制器的"请求并返回",发起网络请求,并且回到上界面(我是用的是AFN3.0)

- (void)requestData {

AFHTTPSessionManager*manager = [AFHTTPSessionManagermanager];

manager.responseSerializer.acceptableContentTypes= [NSSetsetWithObjects:@"text/html",nil];

NSString*url =@"填写你使用的url";

//将父类的属性等于数据请求的返回值

self.task= [managerGET:url parameters:nil progress:^(NSProgress*_NonnulldownloadProgress) {

}success:^(NSURLSessionDataTask*_Nonnulltask,id_NullableresponseObject) {

NSLog(@"success");

}failure:^(NSURLSessionDataTask*_Nullabletask,NSError*_Nonnullerror) {

NSLog(@"failure, error:%@", error);

}];

[self.navigationControllerpopViewControllerAnimated:YES];//返回上一界面

}

让它父类的_task属性等于数据请求的返回值.当执行pop方法的时候.界面会执行-dealloc方法.在-dealloc方法中处理结束请求方法.

- (void)dealloc {

if(self.task) {

[self.task cancel];//取消当前界面的数据请求.

}

}

在此做下判断,当_task创建了,再去取消请求,没有网络请求就不执行.

三.当我们运行的时候,点击"请求并返回"按钮的时候,会直接返回上界面,如果请求时间有点长的话,会先走-dealloc,当取消后,数据请求会直接走failure,并抛出error,Domain=NSURLErrorDomain Code=-999 "cancelled".

当不执行取消的时候,点击按钮,请求时间长的话,也是先走-dealloc,但是没有取消请求,数据请求仍会继续,当请求成功了,会执行success.

此处使用的GET请求,同时POST请求也可以同样使用.

好了,以上就是与大家分享的取消界面的网络请求.有什么不对的还请大神们指出,多交流一下.3Q

相关文章

网友评论

  • 令__狐冲:建议博主看一下架构方面的知识,你这样的做法我觉得不可取。我也正在研究这块,我的网络层是封装好的,不依赖于基类。我现在是把请求类用静态变量存取,然后在基类dealloc里获取到请求类的dataTasks,然后利用for循环遍历,如果请求正在执行或者被挂起,则cancel。但是这样有个确定,dealloc的时候获取到的dataTasks有可能是新push进的界面的task,如果一并取消就会带来问题。所以我想着给NSURLSessionDataTask添加一个控制器归属属性,在基类的dealloc里判断这个task是否属于这个控制器,如果属于并且正在执行或者被挂起,则cancel。但是还未成功 fuck
    _阿南_:想法有实现了吗?
    3f55923d2112:如果你已经有了好的想法,回复解答一下思路 😊
    3f55923d2112:哈哈,我跟你有一样的疑问,正在试图解决。
  • S型身材的猪:如果请求未果,block不会强引用着当前控制器吗?从而使控制器不走dealloc,不走dealloc那为何在dealloc里面取消,是不是该在页面将要消失的时候取消呢
    S型身材的猪:@像风一样的孩子丶 这里有一篇关于我的问题的解释http://www.cocoachina.com/bbs/read.php?tid-454556-page-1.html,但是这篇文章也没有解释到我想要的答案,我用的是ARC
    S型身材的猪:@像风一样的孩子丶 你没有理解我的意思,我的意思并不是说用到了self才会导致强引用。而是没有进入block块,比如一个有关网络请求的block,可能回调已经发生了,但是网络不好,可能没那么快进入block,这时我就退出此界面,从而会导致此揭秘哪无法dealloc,只有等到进入了block之后,此界面才开始释放
    像风一样的孩子丶:@S型身材的猪 block中并没有调用self,如果使用的话,arc使用_ _weak修饰一下,mrc使用_ _block修饰一下。外部的self.task只是接收一下block的返回值。并不会造成循环引用。
  • awindyseason:不好的几点: 1,如果某个界面不需要请求,那么也会执行根类的cancel 方法。2,对象请求完成不会释放而是被Controller持有。3,多个请求要写多个task属性?
    awindyseason:@像风一样的孩子丶 :smile:
    像风一样的孩子丶:@zyh_d708 是这样的。1.task属性是父类的属性,默认是个空,当你的界面不需要请求时不会创建给它赋值的,所以你不调用它,它是不会被执行的。2.此处可以在请求完成之后或者调用cancel之后手动置nil并不影响的。3.这个看情况,如果多个请求只有一个需要撤销请求,就没必要创建多个,用父类的就行。如果多个请求同时发起,并且都有可能被取消,就需要创建多个了。同样的多个task对象可手动进行释放。
  • 天才小L:一个页面,几个请求呢?
    像风一样的孩子丶:@十位数 .h的那个就不用了,一个请求对应一个实例.(多个实例,多个请求,一一对应)
    天才小L:@像风一样的孩子丶 一个实例,多个请求
    像风一样的孩子丶:那就需要对每个请求设置一下NSURLSessionDataTask接受.用相应的task取消请求.可以将这些task写在.m文件作为此类的属性.
  • silence_xz:你在基类中的dealloc方法中进行了取消网络请求的操作,属性@property(nonatomic,strong)NSURLSessionDataTask*task;是不是可以放在.m里,更合理些,除非其他子类要调用这个属性,要放在.h中
    silence_xz:@像风一样的孩子丶 搜嘎
    像风一样的孩子丶:是这样的.不写在.h的时候,你在网络请求的时候无法给task赋值,当task为nil的时候,dealloc中的cancel是不会执行的.
    此外放在.h的话,子类中可以对他操作,随时可以取消网络请求,即使页面没有退出也是可以使用的.

本文标题:iOS取消界面的网络请求

本文链接:https://www.haomeiwen.com/subject/fkhjjttx.html