Convert from ASIHTTPRequest to AFNetworking

I am converting my applications from ASIHTTP to AFNetworking due to an unsuccessful termination of work on this project ... and what I learned later became a much better and smaller AFNetworking code base.

I find a few questions. My code for ASIHTTPRequest is built as a method. This method takes several parameters and sends the parameters to url ... returning the resulting data. This data is always textual, but in the interest of creating a common method, it can sometimes be json, sometimes XML, or sometimes HTML. Thus, I built this method as a standalone universal URL loader.

My problem is that when I call the subroutine I have to wait for an answer. I know that all “synchronous are bad” arguments ... and I don't do this much ... but for some methods I want to synchronize.

So here is my question. Below is my simplified ASIHTTP code, followed by the only way I could code this in AFNetworking. The problem is that AFNetworking is sometimes not responsible for the response before returning from the method. The hint that @mattt gave [operation waitUntilFinished] does not completely withstand the thread until the termination block is called ... and my other method [queue waitUntilAllOperationsAreFinished] does not always work (and DOES NOT cause some error to occur [operation hasAcceptableStatusCode]). So, if someone can help, WITHOUT the ever-present “design asynchronously”, please do.

ASIHTTP Version:

 - (NSString *) queryChatSystem:(NSMutableDictionary *) theDict { NSString *response = [NSString stringWithString:@""]; NSString *theUrlString = [NSString stringWithFormat:@"%@%@",kDataDomain,kPathToChatScript]; ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:theUrlString]]; for (id key in theDict) { [request setPostValue:[theDict objectForKey:key] forKey:key]; } [request setNumberOfTimesToRetryOnTimeout:3]; [request setAllowCompressedResponse:YES]; [request startSynchronous]; NSError *error = [request error]; if (! error) { response = [request responseString]; } return response; } 

AFNetworking Version

 - (NSString *) af_queryChatSystem:(NSMutableDictionary *) theDict { NSMutableDictionary *theParams = [NSMutableDictionary dictionaryWithCapacity:1]; for (id key in theDict) { [theParams setObject:[theDict objectForKey:key] forKey:key]; } AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:kDataDomain]]; NSMutableURLRequest *theRequest = [httpClient requestWithMethod:@"POST" path:[NSString stringWithFormat:@"/%@",kPathToChatScript] parameters:theParams]; __block NSString *responseString = [NSString stringWithString:@""]; AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:theRequest] autorelease]; operation.completionBlock = ^ { if ([operation hasAcceptableStatusCode]) { responseString = [operation responseString]; NSLog(@"hasAcceptableStatusCode: %@",responseString); } else { NSLog(@"[Error]: (%@ %@) %@", [operation.request HTTPMethod], [[operation.request URL] relativePath], operation.error); } }; NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease]; [queue addOperation:operation]; [queue waitUntilAllOperationsAreFinished]; [httpClient release]; return responseString; } 

Thanks so much for any ideas.

+4
source share
3 answers
 - (void)af_queryChatSystem:(NSMutableDictionary *) theDict block:(void (^)(NSString *string))block { ... } 

Now at the end of Block do:

 block(operation.responseString); 
Block

will act as a delegate for the operation. remove

 -waitUntilAllOperationsAreFinished 

and

 return responseString 

You call it the following:

 [YourInstance af_queryChatSystem:Dict block:^(NSString *string) { // use string here }]; 

Hope this helps. You can refer to the iOS example. AFNetworking has

+3
source

I highly recommend using this feature to convert your own NSURLConnection to Apple, rather than accepting another third-party API. Thus, you can be sure that it will not be terminated. I found that the extra work required for his work is minimal - but it turns out to be much more reliable and less error prone.

0
source

My solution manually starts the current runloop of the thread until the callback is processed.

Here is my code.

 - (void)testRequest { MyHTTPClient* api = [MyHTTPClient sharedInstance]; // subclass of AFHTTPClient NSDictionary* parameters = [NSDictionary dictionary]; // add query parameters to this dict. __block int status = 0; AFJSONRequestOperation* request = [api getPath:@"path/to/test" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { // success code status = 1; NSLog(@"succeeded"); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { // failure status = 2; NSLog(@"failed"); }]; [api enqueueHTTPRequestOperation:request]; [api.operationQueue waitUntilAllOperationsAreFinished]; while (status == 0) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate date]]; } STAssertEquals(status, 1, @"success block was executed"); } 
0
source

Source: https://habr.com/ru/post/1381769/


All Articles