AFNetworking cancel post request - afnetworking-2

i know, this question ask before. But not working for me this scenario. i am working on AFNetworking for transfer layer. My code below.
AFHTTPRequestOperation *post;
AFHTTPRequestOperationManager *manager;
AFHTTPRequestOperationManager * manager = [AFHTTPRequestOperationManager manager];
NSMutableDictionary *paramDict = [[NSMutableDictionary alloc] init] ;
delegate = (id<ConnectionUtilDelegate>) delegateObject;
for (Parameter *param in parameterArray)
{
[paramDict setObject:param.value forKey:param.name];
}
NSDictionary *params = paramDict;
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
[manager.operationQueue cancelAllOperations];
post = [manager POST:[NSString stringWithFormat:#"%#",url] parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
[delegate requestCompleted:responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[delegate requestFailed:error];
NSLog(#"Error: %#", error);
}];
this is my post request. it's work like charm. But sometimes some request could be late. For instance, i send 2 different post request this name P1(Post 1) and P2(Post 2). if these request response return as a R1(Response 1) and than R2( response 2) is ok for me. But if this request response return as a R2(Response 2) and than R1(Response 1) its a cause for my app. So i want to cancel old request when i send new request. and
[post cancel];
Error:
[AFHTTPRequestOperation cancel]: message sent to deallocated instance 0x1723cbf0
not working for me. Do you have any suggestion?

As I see in your code, you create a new AFHTTPRequestOperationManagerinstance for each request and then perform cancelAllOperations over the operationQueue of newly created AFHTTPRequestOperationManager. I suggest you creating a sharedManager of type AFHTTPRequestOperationManager and use this singleton object for all your requests:
+ (instancetype)sharedManager {
static AFHTTPRequestOperationManager *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [AFHTTPRequestOperationManager manager];
});
return instance;
}
Then, you can cancel all requests before performing a new request using:
+ (void)cancelAllRequests {
[[AFHTTPRequestOperationManager sharedManager].operationQueue cancelAllOperations];
}
When you call above method, all requests will fail and failureblock will be called. So you need to check if operation is cancelled in failure block. And here comes the final code:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager sharedManager];
NSMutableDictionary *paramDict = [[NSMutableDictionary alloc] init] ;
delegate = (id<ConnectionUtilDelegate>) delegateObject;
for (Parameter *param in parameterArray)
{
[paramDict setObject:param.value forKey:param.name];
}
NSDictionary *params = paramDict;
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
AFHTTPRequestOperation *post = [manager POST:[NSString stringWithFormat:#"%#",url] parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
[delegate requestCompleted:responseObject];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (!operation.cancelled) {
[delegate requestFailed:error];
}
}];
[post start];

Related

Invalid type in JSON write (NSConcreteMutableData)

I am trying to send a JSON request with AFNetworing but following code giving me JSON text did not start with array or object and option to allow fragments not set error:
NSString *post = [[NSString alloc] initWithFormat:
#"{\"request\":\"login\",\"userName\":\"%#\",\"password\":\"%#\"}", userName, password];
NSData *parameters = [post dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *parameterDictionary =
[NSJSONSerialization JSONObjectWithData:parameters options:NSJSONReadingAllowFragments error:nil];
DDLogDebug(#"Data: %#", [parameterDictionary description]);
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
AFHTTPRequestOperation *operation =
[manager POST:WEB_SERVICE_URL parameters:parameterDictionary
success:^(AFHTTPRequestOperation *operation, id responseObject) {
DDLogDebug(#"LoginView - Success Response: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DDLogError(#"LoginView - Error Response: %#", [error description]);
}];
[operation start];
This is the log output of the parameterDictionary object:
{
password = q;
request = login;
userName = q;
}
I have looked similar questions for the error and tried to put parameters object in to an array but this time I got the error "Invalid type in JSON write (NSConcreteMutableData)"
NSMutableArray *array = [NSMutableArray new];
[array addObject:parameterDictionary];
DDLogDebug(#"Data: %#", [parameterDictionary description]);
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
AFHTTPRequestOperation *operation =
[manager POST:WEB_SERVICE_URL parameters:array
success:^(AFHTTPRequestOperation *operation, id responseObject) {
DDLogDebug(#"LoginView - Success Response: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DDLogError(#"LoginView - Error Response: %#", [error description]);
}];
What I am doing wrong?
UPDATE:
I have tried following but it did't work:
NSMutableDictionary *dictionary = [NSMutableDictionary new];
[dictionary setObject:#"login" forKey:#"request"];
[dictionary setObject:#"q" forKey:#"userName"];
[dictionary setObject:#"q" forKey:#"password"];
DDLogDebug(#"Dictionary: %#", [dictionary description]);
DDLogDebug(#"Json: %#", [dictionary JSONRepresentation]);
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager setRequestSerializer:[AFJSONRequestSerializer serializer]];
AFHTTPRequestOperation *operation =
[manager POST:WEB_SERVICE_URL parameters:dictionary
success:^(AFHTTPRequestOperation *operation, id responseObject) {
DDLogDebug(#"LoginView - Success Response: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DDLogError(#"LoginView - Error Response: %#", [error description]);
}];
UPDATE 2:
This what my AFHTTPRequestOperation look like on error block:
<AFHTTPRequestOperation: 0x7fd881fa1200, state: isFinished, cancelled: NO request: <NSMutableURLRequest: 0x7fd881f9fd60> { URL: http://www.olcayertas.com/services.php }, response: <NSHTTPURLResponse: 0x7fd881d913b0> { URL: http://www.olcayertas.com/services.php } { status code: 200, headers {
Connection = close;
"Content-Length" = 1050;
"Content-Type" = "application/json; charset=utf-8";
Date = "Wed, 21 Jan 2015 10:28:45 GMT";
Server = Apache;
"X-Powered-By" = PleskLin;
} }>
The JSON does not seem to validate on JSONlint.com. I would make sure the JSON is correct from there first.
This is what I entered:
{\"request\":\"login\",\"userName\":\"%#\",\"password\":\"%#\"}
I use this to check the JSON:
if ([NSJSONSerialization isValidJSONObject:requestJSONContents]) { }
I have solved the problem by checking my web service in browser. The problem was in my services.php file. There was an error about log file creation and this error was returning a non JSON response that causing the request to fail. My complate working code is here:
NSMutableDictionary *dictionary = [NSMutableDictionary new];
[dictionary setObject:#"login" forKey:#"request"];
[dictionary setObject:#"q" forKey:#"userName"];
[dictionary setObject:#"q" forKey:#"password"];
DDLogDebug(#"Dictionary: %#", [dictionary description]);
DDLogDebug(#"Json: %#", [dictionary JSONRepresentation]);
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager setRequestSerializer:[AFJSONRequestSerializer serializer]];
[manager setResponseSerializer:[AFJSONResponseSerializer serializer]];
//[manager.securityPolicy setAllowInvalidCertificates:true];
AFHTTPRequestOperation *operation =
[manager POST:WEB_SERVICE_URL parameters:dictionary
success:^(AFHTTPRequestOperation *operation, id responseObject) {
DDLogDebug(#"LoginView - Success Response: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DDLogError(#"LoginView - Error Response: %#", [error description]);
DDLogError(#"Error: %#",operation);
}];
[operation start]
And here is my complate services.php file to make it as a complate example for passing and getting JSON with AFNetworiking and PHP service:
PHP web service that accepts JSON input and return JSON response

AFNetworking 2.0 in AFHTTPRequestOperationManager how to pass HTTPBody tag

I am using AFNetworking 2.0, in this I have to pass json object in body part, How to pass HTTP Body in AFHTTPRequestOperationManager.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"foo": #"bar"};
NSURL *filePath = [NSURL fileURLWithPath:#"file://path/to/image.png"];
[manager POST:#"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:filePath name:#"image" error:nil];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Thanks,
Chatting with you offline, it sounds like the main concern is how to send profile image, name, email address, userid, and password in single request. It might look like:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSURL *filePath = ...
[manager POST:#"http://example.com/registration.json" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:filePath name:#"image" error:nil];
[formData appendPartWithFormData:[name dataUsingEncoding:NSUTF8StringEncoding] name:#"name"];
[formData appendPartWithFormData:[email dataUsingEncoding:NSUTF8StringEncoding] name:#"email"];
[formData appendPartWithFormData:[userid dataUsingEncoding:NSUTF8StringEncoding] name:#"userid"];
[formData appendPartWithFormData:[password dataUsingEncoding:NSUTF8StringEncoding] name:#"password"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
No JSON is needed.
If you wanted to use JSON, you can do that, but you wouldn't use the constructingBodyWithBlock method (which creates a multipart/form-data request). Instead, you'd just create a plain old JSON request, e.g.:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
NSDictionary *parameters = #{
#"name" : name,
#"email" : email,
#"userid" : userid,
#"password" : password,
#"image" : base64EncodedImage
};
[manager POST:#"http://example.com/registration.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Clearly, these are very different approaches, so whatever approach you adopt requires that the server code be written to handle the same API.

AFNetworking 2: How to cancel a AFHTTPRequestOperationManager request?

I migrated my networking functionality from AFNetworking to AFNetworking v2 and instead of AFHttpClient I am using AFHTTPRequestOperationManager to support iOS6 as well.
My issue is that while in AFHttpClient there was the functionality to cancel a pending request using the
- (void)cancelAllHTTPOperationsWithMethod:(NSString *)method path:(NSString *)path;
method, in the AFHTTPRequestOperationManager there is no such obvious method.
What I've done up to now is subclassing AFHTTPRequestOperationManager and declaring an iVar
AFHTTPRequestOperation *_currentRequest;
When I make a request the code is something like
- (void)GetSomething:(NSInteger)ID success:(void (^)(MyResponse *))success failure:(void (^)(NSError *))failure
{
_currentRequest = [self GET:#"api/something" parameters:#{#"ID": [NSNumber numberWithInteger:ID]} success:^(AFHTTPRequestOperation *operation, id responseObject) {
MyResponse *response = [MyResponse responseFromDictionary:responseObject];
success(response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
}];
}
and I have a
- (void)cancelCurrentRequest;
methods which all that does is
- (void)cancelCurrentRequest
{
if(_currentRequest) {
[_currentRequest cancel]; _currentRequest = nil;
}
}
Now, I don't think this is good practice and when the method is called I get (NSURLErrorDomain error -999.) which is why I need some advice on getting this done correctly.
Thank you in advance.
Objective-C
[manager.operationQueue cancelAllOperations];
Swift
manager.operationQueue.cancelAllOperations()
You don't have to subclass AFHTTPRequestOperationManager , because when you send request, AFHTTPRequestOperation returns from the
- (AFHTTPRequestOperation *)GET:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
simply save it somewhere or make static and then perform cancel when the request need to be canceled.
Example:
- (void)sendRequestToDoSomething
{
static AFHTTPRequestOperation *operation;
if(operation) //cancel operation if it is running
[operation cancel];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
//configure manager here....
operation = [manager GET:urlString parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
//do something here with the response
operation = nil;
} failure:^(AFHTTPRequestOperation *op, NSError *error) {
{
//handle error
operation = nil;
}

AFNetworking paramaters for Google API

I am trying to send a Google Places API request using AFNetworking.
I have the following code:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager setRequestSerializer:[AFJSONRequestSerializer serializer]];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:OPIA_USERNAME password:OPIA_PASSWORD];
[manager.requestSerializer setValue:API_HEADER_RESPONSE_FORMAT forHTTPHeaderField:#"Accept"];
[manager setResponseSerializer:[AFJSONResponseSerializer serializer]];
parameters = #{#"key": GOOGLE_API_BROWSER_KEY, #"location": "-27.476383,153.014786", #"radius": [NSString stringWithFormat:#"%i", GOOGLE_PLACES_SEARCH_RADIUS], #"sensor": #"true", #"keyword": type, #"opennow": #"true", #"rankby": #"distance"};
requestURL = [NSString stringWithFormat:#"%#%#", GOOGLE_PLACES_API_URL, API_RESPONSE_FORMAT];
[manager GET:requestURL parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
It generates a URL like this:
https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=XXXX&keyword=coffee&location=-27.476383%2C153.014786&opennow=true&radius=100&rankby=distance&sensor=true.
As you can see, the "," in the location parameter is being encoded by AFNetworking.
I am using AFNetworking 2.0.
I use ut this way like this:
NSString* urlString = [NSString stringWithFormat:GOOGLE_PLACES_API_JSON, latitude,longitude, radius, types];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:urlString
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
//do stuff
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//show error
}];
I had to move away from the "parameters" approach, and instead manipulate the URL string.

AFJSONRequestOperation returns null response in iOS

I am facing 1 problem while using AFJSONRequestOperation. My API Client is as follows
#import <Foundation/Foundation.h>
#import "AFHTTPClient.h"
#import "AFJSONRequestOperation.h"
#interface MyAPIClient : AFHTTPClient
+ (MyAPIClient *)sharedAPIClient;
#end
// .m file
#import "MyAPIClient.h"
#implementation MyAPIClient
+ (MyAPIClient *)sharedAPIClient {
static MyAPIClient *sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedClient = [[MyAPIClient alloc] initWithBaseURL:[NSURL URLWithString:kBASE_URL]];
});
return sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (!self) {
return nil;
}
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setDefaultHeader:CONTENT_TYPE_FIELD value:CONTENT_TYPE_JSON_VALUE];
self.parameterEncoding = AFJSONParameterEncoding;
return self;
}
#end
Now when I request with following code it returns me "null" response
NSDictionary *params = [[NSDictionary alloc]initWithObjectsAndKeys:userName,#"email",password,#"password",nil];
NSMutableURLRequest *request = [[MyAPIClient sharedAPIClient] requestWithMethod:#"POST" path:#"login" parameters:params];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
{
NSDictionary *dictResponse = (NSDictionary*)JSON;
DLog(#"Login Success JSON: %#",JSON);
if (block) {
block(YES,nil);
}
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
DLog(#"Login Error:- %#",error);
if (block) {
block(NO,error);
}
}];
[operation start];
But when I use AFHTTPRequestOperation it reurns me correct output with logged in used info
NSURL *loginUrl = [NSURL URLWithString:kBASE_URL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:loginUrl];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
userName,#"email",password,#"password",nil];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:#"login" parameters:params];
//Notice the different method here!
AFHTTPRequestOperation *operation = [httpClient HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"Raw data Response: %#", responseObject);
NSMutableArray *jsonArray = [NSJSONSerialization JSONObjectWithData:responseObject options:kNilOptions error:nil];
NSLog(#"Converted JSON : %#", jsonArray);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error){
NSLog(#"Error: %#", error);
}];
//Enqueue it instead of just starting it.
[httpClient enqueueHTTPRequestOperation:operation];
My server returns JSON response.
What is the problem in above code? Why AFJSONRequestOperation returns null response while
AFHTTPRequestOperation returns me correct response ? Any kind of help is appreciated. Thanks in advance