1. 程式人生 > >iOS開發 取消之前已經發送的Http請求

iOS開發 取消之前已經發送的Http請求

我有一個TextField,無論什麼時候當我輸入字元的時候,我appending這個字元到我的url,然後傳送一次請求,我現在

需要取消之前的請求。例如當我輸入“shampoo”的時候,我會觸發7次代理方法,也就是我會觸發七次不同的網路請

求,那麼有一個問題,這七次發出的請求,響應的順序可不是你想的按順序返回的,例如傳送的是1234567,那麼返回

資料很有可能是1234576,這樣導致最後需要的結果不是“7”,而是“6”。那麼看看我是如何解決的以及遇到坑的!!!

1.第一種解決方案(失敗)

[NSObject cancelPreviousPerformRequestsWithTarget:self];

我看到了這個方法,最終測試的結果是,它只能取消掉還未進行網路請求的方法 如下所示

[selfperformSelector:@selector(startSearchRefresh) withObject:nilafterDelay:0.5];

在這個delay的0.5秒以內,如果我再次觸發該方法,那麼,第一個方法就會取消掉之前還在delay的方法,從而達到目的

但是如果到了0.5秒,方法已經進行http請求了呢,已經在請求的過程中了呢,這個方法是根本取消不掉的。

因此,這個方法可以用於使用者快速輸入的時候後一次操作覆蓋前一次操作,對我來說還是失敗的方法

2.第二種解決方案(失敗)

當我進行網路請求的時候

[manager.operationQueue cancelAllOperations];

獲取到AFNetWorking的物件的時候,拿到它的任務佇列,然後取消掉之前所有的任務,我不知道是不是版本的問題,

最新的AF(3.0)以上貌似根本沒什麼用,也有可能是我的插入方式有問題吧

來看看一個老外的實時搜尋的程式碼段,根本沒取消掉

  1. -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString
     *)string;  
  2. {  
  3.     //[self.s_searchResultText setHidden:YES];
  4.     // [SVProgressHUD dismiss];
  5.     [self.s_tableView setHidden:true];  
  6.     [searchProductArray removeAllObjects];  
  7.     [self.s_tableView reloadData];  
  8.     NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:UNACCEPTABLE_CHARACTERS] invertedSet];  
  9.     NSLog(@"%@",cs);  
  10.     NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];  
  11.     NSLog(@"%@",filtered);  
  12.     NSLog(@"%lu",(unsigned long)filtered.length);  
  13.     if (filtered.length) {  
  14.         [CustomToastAlert showToastInParentView:self.view withText:@"Please enter valid characters" withDuaration:1.5];  
  15.         returnNO;  
  16.     }  
  17.     searchTextString = [textField.text stringByAppendingString:string];  
  18.     NSLog(@"%lu",(unsigned long)[searchTextString length]);  
  19.     NSLog(@"%@",searchTextString);  
  20.     int stringLength=[searchTextString length];  
  21.     constcharchar * _char = [string cStringUsingEncoding:NSUTF8StringEncoding];  
  22.     int isBackSpace = strcmp(_char, "\b");  
  23.     if (isBackSpace == -8) {  
  24.         stringLength=[searchTextString length];  
  25.         stringLength=[searchTextString length]-1;  
  26.         searchTextString=[searchTextString substringToIndex:stringLength];  
  27.         NSLog(@"Backspace was pressed");  
  28.         NSLog(@"string is %@",searchTextString);  
  29.     }  
  30.     if(stringLength>=3)  
  31.     {  
  32.         AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] init];  
  33.         manager.responseSerializer = [AFJSONResponseSerializer serializer];  
  34.         NSString *urlString=[NSString stringWithFormat:kSearchProductUrl,kBaseUrl];  
  35.         urlString = [urlString stringByAppendingString:searchTextString];  
  36.         urlString = [urlString stringByReplacingOccurrencesOfString:@" " withString:@"%20"];  
  37.         NSLog(@"%@",searchTextString);  
  38.         NSLog(@"%@",urlString);  
  39.         [searchProductArray removeAllObjects];  
  40.        // [manager invalidateSessionCancelingTasks:NO];
  41.         //[manager.operationQueue cancelAllOperations];
  42.         [manager GET:urlString parameters:nil success:^(NSURLSessionDataTask *task, id responseObject)  
  43.          {  
  44.              [searchProductArray removeAllObjects];  
  45.              //[SVProgressHUD showWithStatus:LOADING_ITEMS maskType:SVProgressHUDMaskTypeGradient];
  46.              NSLog(@"JSON: %@", responseObject);  
  47.              json= responseObject;  
  48.              NSLog(@"%@",json);  
  49.              NSLog(@"%lu",(unsigned long)[[json valueForKeyPath:@"data"] count ]);  
  50.              for(int i=0;i<[[json valueForKeyPath:@"data"]count ];i++)  
  51.              {  
  52.                  Product *s_productList=[[Product alloc]init];  
  53.                  s_productList.SKU_Name=[[json valueForKeyPath:@"data.sku_name"]objectAtIndex:i];  
  54.                  s_productList.SKU_Id=[[json valueForKeyPath:@"data.sku_id"]objectAtIndex:i];  
  55.                  s_productList.SKU_Price=[[json valueForKeyPath:@"data.sku_price"]objectAtIndex:i];  
  56.                  s_productList.SKU_OfferPrice=[[json valueForKeyPath:@"data.sku_offer_price"]objectAtIndex:i];  
  57.                  s_productList.SKU_Currency = RUPEE_SYMBOL;  
  58.                  s_productList.SKU_AvailableUnit=[[json valueForKeyPath:@"data.sku_available_unit"]objectAtIndex:i];  
  59.                  s_productList.SKU_OfferDescription= [[json valueForKeyPath:@"data.sku_offer_desc"]objectAtIndex:i];  
  60.                  s_productList.SKU_ImageUrls=[[json valueForKeyPath:@"data.sku_image_urls"]objectAtIndex:i];  
  61.                  [searchProductArray addObject:s_productList];  
  62.                  NSLog(@"%lu",(unsigned long)[searchProductArray count]);  
  63.              }  
  64.              [self.s_tableView setHidden:FALSE];  
  65.              [self.s_tableView reloadData];  
  66.              NSLog(@"%lu",(unsigned long)[searchProductArray count]);  
  67.              if ([searchProductArray count]==0) {  
  68.                  [CustomToastAlert showToastInParentView:self.view withText:SEARCH_RESULT withDuaration:1.5];  
  69.              }  
  70.          }  
  71.              failure:^(NSURLSessionDataTask *task, NSError *error)  
  72.          {  
  73.              [CustomToastAlert showToastInParentView:self.view withText:NO_DATA_AVAIL withDuaration:1.5];  
  74.          }];  
  75.     }  
  76.     returnYES;  
  77. }  

3.第三種解決方法,這個才是我最終的解決方案

該方法也是從stackOverFlow上找來的,真的是找死我了

以上面的程式碼段為例,他是這麼操作的

主要精髓在於

第一點:不要initialize a new AFHTTPSessionManager object everytime 一定要把manager用成全域性的

第二點:把請求返回的task物件丟進陣列,下次觸發的時候把遍歷陣列,把之前的所有任務[task cancel]

  1. // somewhere in your class, let's say in ViewDidLoad you should init the AFHTTPSessionManager object
  2. - (void)viewDidLoad {  
  3.     [super viewDidLoad];  
  4.     /// create the AFHTTPSessionManager object, we're gonna use it in every request
  5.     self.manager = [[AFHTTPSessionManager alloc] init];  
  6.     self.manager.responseSerializer = [AFJSONResponseSerializer serializer];  
  7.     /// 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
  8.     self.arrayOfTasks = [NSMutableArray new];  
  9.     /// discussion:
  10.     /// an array holds multiple objects. if you just want to hold a ref to the latest task object
  11.     /// then create a property of NSURLSessionDataTask instead of NSMutableArray, and let it point to the latest NSURLSessionDataTask object you create
  12. }  
  13. -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;{  
  14.     /// your code goes here
  15.     /// .....
  16.     /// .....
  17.     /// .....
  18.     /// .....
  19.     /// till we reach
  20.     if(stringLength>=3){  
  21.         /// cancel all previous tasks
  22.         [self.arrayOfTasks enumerateObjectsUsingBlock:^(NSURLSessionDataTask *taskObj, NSUInteger idx, BOOLBOOL *stop) {  
  23.             [taskObj cancel]; /// when sending cancel to the task failure: block is going to be called
  24.         }];  
  25. 相關推薦

    iOS開發 取消之前已經Http請求

    我有一個TextField,無論什麼時候當我輸入字元的時候,我appending這個字元到我的url,然後傳送一次請求,我現在 需要取消之前的請求。例如當我輸入“shampoo”的時候,我會觸發7次代理方法,也就是我會觸發七次不同的網路請 求,那麼有一個問題,這七次發出的請求,響應的順序可不是你想的按

    iOS開發中如遇到頻繁的Http請求,如何取消之前已經Http請求?

    我有一個TextField,無論什麼時候當我輸入字元的時候,我appending這個字元到我的url,然後傳送一次請求,我現在需要取消之前的請求。例如當我輸入“shampoo”的時候,我會觸發7次代理方法,也就是我會觸發七次不同的網路請求,那麼有一個問題,這七次發出的請求,響

    Android開發,使用RetrofitHTTP請求

    service fin tps protect convert exceptio code find content 在build.gradle(Module: app)中加入 dependencies { ... implementation ‘com.

    nodejs通過代理(proxy)http請求(request)

    same pan response main only ext ejs https status 有可能有這樣的需求,需要node作為web服務器通過另外一臺http/https代理服務器發http或者https請求,廢話不多說直接上代碼大家都懂的: var http =

    HttpUtils http請求工具類

    encoding entryset closeable .get 調用 fig lin nal ping import java.io.IOException; import java.io.UnsupportedEncodingException; import jav

    android http請求

    ans xxx pub 輸入 項目 建立 run 第一行代碼 pack 好久沒寫博客了,由於公司要做android,筆者也是第一次接觸。 這是在項目中遇到一個比較麻煩的問題。記錄下來備忘(本人剛接觸。有不正確的地方請不吝賜教)。 發送請求的代碼:

    C/C++使用libcurl庫http請求(get和post可以用於請求html信息,也可以請求xml和json等串)

    網絡連接 get 編譯 eas views vs2015 return tar linux C++要實現http網絡連接,需要借助第三方庫,libcurl使用起來還是很方便的 環境:win32 + vs2015 如果要在Linux下使用,基本同理 1,下載

    後臺http請求通用方法,包括get和post

    util line 通用方法 返回 finall 6.0 val except ktr package com.examsafety.service.sh; import java.io.BufferedReader; import java.io.IOExceptio

    使用RequestsHttp請求

    requests安裝Requests第三方庫:在命令行輸入pip install requests官方中文版文檔地址:http://cn.python-requests.org/zh_CN/latest/user/quickstart.html#id2使用Requests發送Http請求

    RNhttp請求例子

    sed json pre xxx new rand date error ken 發送http請求 let map = { method: ‘post‘, headers: { token: ‘‘,

    java通過java.net.URLhttp請求調用接口

    urn color val return http 功能 enc nts 實例 一般在*.html,*.jsp頁面中我們通過使用ajax調用接口,這個是我們通常用的。對於這些接口,大都是本公司寫的接口供自己調用,所以直接用ajax就可以。但是,如果是多家公司共同開發一個東西

    webpack + vue 向本地後端http請求跨域問題

    contex con blog 方法 point 原來 文件 string lte 一、問題描述 前端: webpack + vue + axios 後端: wamp + php 用webpack訪問前端頁面是需要一個端口的,後端服務器也是需要一個端口的,端口不同,在本地調

    一個常用的通過curlHTTP請求的函數

    請求方式 multi return ini als 參數 一個 pic def function: function curl_get($url, $params) { return curl_http($url, $params, ‘GET‘); } func

    springboothttp請求

    local exchange 情況下 app media oot 下午 pri bsp springboot中實現http請求調用api創建發送http請求service層import org.springframework.http.*; import org.sprin

    使用Fiddler模擬Http請求

    mage bubuko image png http請求 alt 使用 技術 inf 模擬GET請求: GET請求比較簡單,接下來說下模擬POST請求: 比如這裏模擬POST發送JSON數據。 接下來可以在這裏查看請求結果: 使用Fiddler模擬發送Http請求

    PHP的3種HTTP請求的方式

    default 管理 mon class 防止 列表 密碼 value opera 1.cURL <?php class IndexController extends ControllerBase { public function indexActi

    使用javaHTTP請求

    catch msi static bsp nal string pro nbsp exceptio 1 public class Test { 2 public static void main(String[] args) { 3 Buff

    跨域HTTP請求詳解

    ext open author read stat 請求 buffere keyset post ------------吾亦無他,唯手熟爾,謙卑若愚,好學若饑------------- 本篇博客講述幾種跨域發HTTP請求的幾種方

    HTTP請求內容過長失敗解決方案

    conn cti leg 問題分析 tro edi ont direct con tomcat 報錯 java.lang.IllegalArgumentException: Request header is too large 問題分析: 請求頭超過了tomcat的限

    PHP編程中使用CURLHTTP請求的基本流程

    size 常量 col 科技 比較 編碼 如何使用 lse 正文 在PHP編程中,有時候需要編程技術人員使用CURL的PHP擴展完成一個HTTP請求的發送,對於這個操作來說,很多初學者都會遇到很多苦難,那麽下面就來為大家講解一下。一般有以下幾個步驟:   1. 初始化連接句