I have a textfield, whenever I enter a character, I appending this character to my URL, and then send a request to me now
A previous request needs to be canceled. For example, when I enter "shampoo", I will trigger 7 proxy methods, that is, I will trigger seven different networks please
Please, then there is a problem, these seven requests, the order of response is not the sequence you want to return, such as sending a 1234567, then return
The data is likely to be 1234576, which results in a "7" rather than a "6" result of the final need. So look how I solved it and met the pit ...
1. The first solution (failure)
[NSObject cancelpreviousperformrequestswithtarget:self]; I see this method, and the result of the final test is that it only cancels out the method that has not yet made the network request as follows
[Self performselector: @selector (Startsearchrefresh) Withobject:nil afterdelay:0.5];
Within 0.5 seconds of this delay, if I trigger the method again, the first method will cancel the method that was delay before and achieve the goal
But if in 0.5 seconds, the method has been HTTP request, already in the process of the request, this method is simply canceled.
Therefore, this method can be used for the user to quickly enter the time when the next operation overwrites the previous operation, for me or Failed method
2. The second solution (failure)
When I make a Web request,
[Manager.operationqueue cancelalloperations];
Get to the Afnetworking object, get its task queue, then cancel all previous tasks, I don't know if it's a version of the problem,
The latest AF (3.0) above seems to have no use, it may be my way of inserting a problem
Take a look at a foreigner's real Time search code snippet, did not cancel out
-(BOOL) TextField: (Uitextfield *) TextField Shouldchangecharactersinrange: (nsrange) range replacementstring: (
NSString *) string;
{//[self.s_searchresulttext Sethidden:yes];
[Svprogresshud dismiss];
[Self.s_tableview Sethidden:true];
[Searchproductarray removeallobjects];
[Self.s_tableview Reloaddata];
Nscharacterset *cs = [[Nscharacterset charactersetwithcharactersinstring:unacceptable_characters] invertedSet];
NSLog (@ "%@", CS);
NSString *filtered = [[string Componentsseparatedbycharactersinset:cs] componentsjoinedbystring:@ "];
NSLog (@ "%@", filtered);
NSLog (@ "%lu", (unsigned long) filtered.length); if (filtered.length) {[Customtoastalert showToastInParentView:self.view withtext:@ ' Please enter valid characters '
WITHDUARATION:1.5];
return NO;
} searchtextstring = [Textfield.text stringbyappendingstring:string];
NSLog (@ "%lu", (unsigned long) [searchtextstring length]);
NSLog (@ "%@", searchtextstring); Int Stringlength=[searchtextstring length];
const char * _char = [string cstringusingencoding:nsutf8stringencoding];
int isbackspace = strcmp (_char, "\b");
if (Isbackspace = = -8) {stringlength=[searchtextstring length];
Stringlength=[searchtextstring length]-1;
Searchtextstring=[searchtextstring Substringtoindex:stringlength];
NSLog (@ "Backspace was pressed");
NSLog (@ "string is%@", searchtextstring);
} if (stringlength>=3) {Afhttpsessionmanager *manager = [[Afhttpsessionmanager alloc] init];
Manager.responseserializer = [Afjsonresponseserializer serializer];
NSString *urlstring=[nsstring Stringwithformat:ksearchproducturl,kbaseurl];
URLString = [URLString stringbyappendingstring:searchtextstring];
URLString = [urlstring stringbyreplacingoccurrencesofstring:@ "" withstring:@ "%20"];
NSLog (@ "%@", searchtextstring);
NSLog (@ "%@", urlstring); [Searchproductarray Removeallobjects];
[Manager Invalidatesessioncancelingtasks:no];
[Manager.operationqueue cancelalloperations];
[Manager get:urlstring Parameters:nil success:^ (nsurlsessiondatatask *task, id responseobject)
{[Searchproductarray removeallobjects];
[Svprogresshud Showwithstatus:loading_items masktype:svprogresshudmasktypegradient];
NSLog (@ "JSON:%@", responseobject);
Json= Responseobject;
NSLog (@ "%@", JSON);
NSLog (@ "%lu", (unsigned long) [[JSON valueforkeypath:@ ' data '] count]; for (int i=0;i<[[json valueforkeypath:@ "data"]count];i++) {Product *s_productlist=[[prod
UCT Alloc]init];
S_productlist.sku_name=[[json valueforkeypath:@ "Data.sku_name"]objectatindex:i];
S_productlist.sku_id=[[json valueforkeypath:@ "data.sku_id"]objectatindex:i]; S_productlist.sku_price=[[json Valueforkeypath:@ "Data.sku_price"]objectatindex:i];
S_productlist.sku_offerprice=[[json valueforkeypath:@ "Data.sku_offer_price"]objectatindex:i];
S_productlist.sku_currency = Rupee_symbol;
S_productlist.sku_availableunit=[[json valueforkeypath:@ "Data.sku_available_unit"]objectAtIndex:i];
s_productlist.sku_offerdescription= [[JSON valueforkeypath:@ ' Data.sku_offer_desc ']objectatindex:i];
S_productlist.sku_imageurls=[[json valueforkeypath:@ "Data.sku_image_urls"]objectatindex:i];
[Searchproductarray addobject:s_productlist];
NSLog (@ "%lu", (unsigned long) [Searchproductarray Count]);
} [Self.s_tableview Sethidden:false];
[Self.s_tableview Reloaddata];
NSLog (@ "%lu", (unsigned long) [Searchproductarray Count]); if ([Searchproductarray count]==0) {[Customtoastalert ShowToastInParentView:self.view withText:search_result withduaration:1.5]; } failure:^ (Nsurlsessiondatatask *task, Nserror *error) {[Customtoastale
RT ShowToastInParentView:self.view Withtext:no_data_avail withduaration:1.5];
}];
return YES; }
3. The third solution, this is my final solution
The method was also found on the StackOverflow, it really killed me.
Take the code snippet above as an example, and that's how he does it.
The main essence is
1th: Do not initialize a new Afhttpsessionmanager object everytime must use the manager as a global
2nd: Throw the Task object returned by the request into the array, the next time the trigger is to iterate over the array, put all previous tasks [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 it 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 are 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 Create}-(BOOL) TextField: (Uitextfield *) TextField Shouldchangecharactersinrange: (nsrange) Range replacementstring: (NSString *) string; {///Your code goes here///...///...///...///...///till we-if (stringlength>=3) {///Cancel all previous tasks [sel F.arrayoftasks enumerateobjectsusingblock:^ (nsurlsessiondatatask *taskobj, Nsuinteger idx, BOOL *stop) {[Task OBJ Cancel];
When sending Cancel to the task Failure:block are going to be called}];
Empty the Arraoftasks [Self.arrayoftasks removeallobjects]; Init new Task Nsurlsessiondatatask *task = [Self.manager get:urlstring parameters:nil success:^ (Nsurlsessionda
Tatask *task, id responseobject) {///Your code}failure:^ (nsurlsessiondatatask *task, Nserror *error) {
Your code}];
Add the task to our arrayoftasks [self.arrayoftasks addobject:task];
return YES; }
Note:
the task Cancel test here does cancel the network request, and you can look at the log below, and remember that this does not mean no callback after cancel .
, just will be back to the error of the block inside, you need information can be tested, in the error hit a breakpoint can be debugged out
View the status of a network task [Articleinterface.articlearraytask enumerateobjectsusingblock:^ (Nsurlsessiondatatask *taskObj, Nsuinteger idx, BOOL *stop) {ddlogverbose (@ "The status of the network task before deleting the current article is ==================>>>>>%ld",
Taskobj.state); [Taskobj Cancel]; When sending Cancel to the task Failure:block are going to be called ddlogverbose (@ "The current article deleted after the network task status is ===============
===>>>>>%ld ", taskobj.state);
}]; typedef ns_enum (Nsinteger, nsurlsessiontaskstate) {nsurlsessiontaskstaterunning = 0,/* the task is currently being serviced by the session * * nsurlsessiontaskstatesuspended = 1, nsurlsessiontaskstatecanceling = 2,/* The task has been told to cancel. The session would receive a URLSession:task:didCompleteWithError:message. * * nsurlsessiontaskstatecompleted = 3,/* The task has completed and the session'll receive no MOR e Delegate notifications */} ns_enum_available (Nsurlsession_available, 7_0);
Print Log 2 Delegates here are nsurlsessiontaskstatecanceling
OK, perfect solution