Can anybody tell me why my call "timed out"? My app just hangs there, the success:^(NSURLSessionTask* operation, id response) section of the folowing code was never executed.
return [self beginRequestController:#"myController" action:#"myAction" parameters:parameters
success:^(NSURLSessionTask* operation, id response)
{
NSLog(#"This is NOT being called --->>>: %#", response);
} failure:^(NSURLSessionTask* operation, NSError* error)
{
//Handle the error
}];
- (NSOperation*) beginRequestController:(NSString*)controller action: (NSString*)action parameters:(NSDictionary*)parameters success: (RequestSuccess)success failure:(RequestFailure)failure
{
NSOperation *operation = [AFHTTPSessionOperation operationWithManager:manager HTTPMethod:#"POST" URLString:urlString parameters:parameters uploadProgress:nil downloadProgress: nil success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(#"Reponse --->>>: %#", responseObject );
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"Error --->>>: %#", error);
}];
[self.operationQueue addOperation:operation];
return operation;
}
You're passing blocks to beginRequestController, but that method doesn't do anything with them. You want to call those blocks. E.g.
- (NSOperation *)beginRequestController:(NSString *)controller action:(NSString *)action parameters:(NSDictionary *)parameters success:(RequestSuccess)success failure:(RequestFailure)failure {
NSOperation *operation = [AFHTTPSessionOperation operationWithManager:manager HTTPMethod:#"POST" URLString:urlString parameters:parameters uploadProgress:nil downloadProgress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(#"Response --->>>: %#", responseObject);
if (success)
success(task, responseObject);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"Error --->>>: %#", error);
if (failure)
failure(task, error);
}];
[self.operationQueue addOperation:operation];
return operation;
}
Or, even simpler:
- (NSOperation *)beginRequestController:(NSString *)controller action:(NSString *)action parameters:(NSDictionary *)parameters success:(RequestSuccess)success failure:(RequestFailure)failure {
NSOperation *operation = [AFHTTPSessionOperation operationWithManager:manager HTTPMethod:#"POST" URLString:urlString parameters:parameters uploadProgress:nil downloadProgress: nil success:success failure:failure];
[self.operationQueue addOperation:operation];
return operation;
}
Related
I have class that manages connections with AFNetworking.
So I want to call my function like NSDictionary *dict = [ServerManager requestWithURL:#"https://someurl.com"];
And that's the function in the other class:
- (NSDictionary *) requestWithURL:(NSString *)requestURL {
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] init];
[manager GET:requestURL parameters:nil progress:nil
success:^(NSURLSessionDataTask *operation, id responseObject){
return responseObject;
}
failure:^(NSURLSessionDataTask *operation, NSError *error) {
}];
}
I know that is incorrect to do that. So what should I do to return responseObject back to NSDictionary *dict? I'd like to get the basic idea of asynchronous development with blocks.
Since the networking request completes long after its is launched, the only way to handle the result is with a block passed to your request method...
// when request completes, invoke the passed block with the result or an error
- (void)requestWithURL:(NSString *)requestURL completion:(void (^)(NSDictionary *, NSError *))completion {
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] init];
[manager GET:requestURL parameters:nil progress:nil success:^(NSURLSessionDataTask *operation, id responseObject){
if (completion) completion((NSDictionary*)responseObject, nil);
}, failure:^(NSURLSessionDataTask *operation, NSError *error) {
if (completion) completion(nil, error);
}];
}
Make it public in a ServerManager.h
- (void)requestWithURL:(NSString *)requestURL completion:(void (^)(NSDictionary *, NSError *))completion;
Elsewhere, call it:
[ServerManager requestWithURL:#"http://someurl.com" completion:^(NSDictionary *dictionary, NSError *error) {
// check error and use dictionary
}];
I'm using AFNetworking and i have a question about it, i want call one different function when return value correct
- (AFHTTPRequestOperation *)GET:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:#"GET" URLString:URLString parameters:parameters success:^(AFHTTPRequestOperation
*requestOperation, __unused id responseObject) {
if (success) {
int status = [[responseObject objectForKey:#"Status"] intValue];
else if(status == -1)
{
[self HTTPRequestOperationWithHTTPMethod:#"GET" URLString:URLString parameters:parameters success:^(AFHTTPRequestOperation *requestOperation, __unused id responseObject) {
if (success) {
NSLog(#"adfasdfasdfasdf");
success(requestOperation,responseObject);
}
} failure:^(AFHTTPRequestOperation * operation, NSError *error) {
NSLog(#"ERROR: %#", error);
failure(nil, error);
}];
}
else
success(requestOperation,responseObject);
}
} failure:failure];
operation.securityPolicy.allowInvalidCertificates = YES;
operation.securityPolicy.validatesDomainName = NO;
[self.operationQueue addOperation:operation];
return operation;
}
when status = -1. I'll call more function with param above, but dosen't work.
else if(status == -1)
{
[self HTTPRequestOperationWithHTTPMethod:#"GET" URLString:URLString parameters:parameters success:^(AFHTTPRequestOperation *requestOperation, __unused id responseObject) {
if (success) {
NSLog(#"adfasdfasdfasdf");
success(requestOperation,responseObject);
}
} failure:^(AFHTTPRequestOperation * operation, NSError *error) {
NSLog(#"ERROR: %#", error);
failure(nil, error);
}];
}
run app and I bug function not call to success or failure.
You don't need to check success of failure with condition in AFNetworking. AFNetworking provide block.
Follow below code :
- (AFHTTPRequestOperation *)GET:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:#"GET" URLString:URLString parameters:parameters success:^(AFHTTPRequestOperation
*requestOperation, __unused id responseObject) {
int status = [[responseObject objectForKey:#"Status"] intValue];
if(status == -1)
{
[self HTTPRequestOperationWithHTTPMethod:#"GET" URLString:URLString parameters:parameters success:^(AFHTTPRequestOperation *requestOperation, __unused id responseObject) {
NSLog(#"adfasdfasdfasdf");
success(requestOperation,responseObject);
} failure:^(AFHTTPRequestOperation * operation, NSError *error) {
NSLog(#"ERROR: %#", error);
failure(nil, error);
}];
}
else
success(requestOperation,responseObject);
}
} failure:failure];
operation.securityPolicy.allowInvalidCertificates = YES;
operation.securityPolicy.validatesDomainName = NO;
[self.operationQueue addOperation:operation];
return operation;
}
if (success) {
int status = [[responseObject objectForKey:#"Status"] intValue];
else if(status == -1)
{
are you sure this if and else if are a pair?
I want to pass the 'NSString' as a parameter for as URLString in below method, how can we do that
-(void)makeServiceCallSuccess:(void (^)(NSDictionary *response))success
failure:(void (^)(NSError *error))failure {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:URLString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
response = (NSDictionary *)responseObject;
success(response);
NSLog(#"JSON: %#", response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
NSLog(#"Error: %#", error);
}];
}
simply add parameter in method, as usually we are doing like
-(void)makeServiceCallSuccessWithURLString:(NSString*)urlString withResponseHandler:(void (^)(NSDictionary *response))success
failure:(void (^)(NSError *error))failure
There is no wat to pass a paramether in that method as it, you can edit it and add a parameter or read a value from aproperty
-(void)makeServiceCallSuccess:(void (^)(NSDictionary *response))success
failure:(void (^)(NSError *error))failure {
NSString* myString = self.myProperty;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:myString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
response = (NSDictionary *)responseObject;
success(response);
NSLog(#"JSON: %#", response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
NSLog(#"Error: %#", error);
}];
}
How can I run multiple requests inside the success block of 1 request and wait for it to finish?
[manager GET:url parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%# Response: \n%#", url, responseObject);
resultsArray = [[NSMutableArray alloc] init];
for (NSDictionary *json in [responseObject objectForKey:#"items"]) {
[self getDetails:json];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[SVProgressHUD dismiss];
}];
Where in getDetails:(id)json is the method to load the group of requests whose parameters are based on the result of the main request.
For example:
I would like to request from the API a list of students, then on the success block. For each student, I would like to get the related data from another table (another request) and put them on my NSObject.
EDIT Here is my getDetails method
- (AFHTTPRequestOperation *)getDetails:(NSDictionary *)json
{
NSLog(#"Start Op %#",[json objectForKey:#"related_salon"]);
NSString *url = [NSString stringWithFormat:#"%#read/salons/%#",SERVER_API_URL,[json objectForKey:#"related_salon"]];
NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:req];
//op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success %#",[json objectForKey:#"name"]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failed Op %#",error.localizedDescription);
}];
//AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:req];
//op.responseSerializer = [AFJSONResponseSerializer serializer];
[op start];
return op;
}
The AFNetworking GET method returns a ATHTTPRequestOperation (an NSOperation subclass). You could have your getDetails method return that object. You can then create a new operation dependent upon those operations, which you'd run at the end:
NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
// add here whatever you want to perform when all the getDetails calls are done,
// e.g. maybe you want to dismiss your HUD when all the requests are done.
[SVProgressHUD dismiss];
}];
[manager GET:url parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%# Response: \n%#", url, responseObject);
resultsArray = [[NSMutableArray alloc] init];
for (NSDictionary *json in [responseObject objectForKey:#"items"]) {
NSOperation *operation = [self getDetails:json];
[completionOperation addDependency:operation];
}
[[NSOperationQueue mainQueue] addOperation:completionOperation];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[SVProgressHUD dismiss];
}];
Again, this is presuming that getDetails is doing its own GET call, and that you change getDetails to (a) capture the NSOperation returned by GET and (b) return it.
I am using AFNetworking 2.0 for networking of my application, I have implemented a method to check the login of a user
-(NSString *) loginWith : (NSString *) email andPassword :(NSString *) password
{
__block NSString * result ;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = #{#"email": email, #"password": password};
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager POST:[kROOT_URL stringByAppendingString:#"auth/"] parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"JSON: %#", (NSDictionary*)responseObject);
[[NSUserDefaults standardUserDefaults] setObject:responseObject forKey:USER_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
result = [responseObject objectForKey:#"id"];
NSLog(#"result :: %#",result);
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#", error);
result = nil;
}];
return result;
}
and from other view controller I am invoking this method :
NSString * result = [self.user loginWith:emailCell.textField.text andPassword:passCell.textField.text];
NSLog(#"Result: %#",result);
the problem is that I get "null" as the object of result, This is because that when the NSlog is executed the network process was doing in background thread, so how I correct the implementation, so then I can get the result in the right moment, after fetching
Thank you
You should add a “callback“ block parameter to your method signature, and call that block when the request is done.
- (void)loginWith:(NSString *)email andPassword:(NSString *)password complete:(void(^)(id result, NSError *error))block {
// ...
[manager POST:[kROOT_URL stringByAppendingString:#"auth/"] parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject)
{
// ...
result = [responseObject objectForKey:#"id"];
if (block) block(result, nil)
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
if (block) block(nil, error)
}];
}
When calling the method, pass the callback block where you can read the result value:
[self.user loginWith:emailCell.textField.text andPassword:passCell.textField.text complete:^(id result, NSError *error) {
if (error)
NSLog(#"Error: %#", error);
else
NSLog(#"Result: %#", result);
}];