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);
}];
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
}];
In this i am sending the header and Add perameters to hitting the web service. the problem is after hitting the web service controller is not going in to success part sometimes. if it is hitting properly then it will return the result in bytes.
This is My code::
AFHTTPRequestOperationManager *manager =[AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager.requestSerializer setTimeoutInterval:300];
manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
//giving the correct format to json
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
token=[parameters valueForKey:#"token"];
if(token == nil || [token isEqual:[NSNull null]]){
token=[[[NSUserDefaults standardUserDefaults]dictionaryForKey:#"LoginWebData"]valueForKey:#"token"];
}else{
token=[parameters valueForKey:#"token"];
}
//set the header do http request
[manager.requestSerializer setValue:[NSString stringWithFormat:#"%#",token]forHTTPHeaderField:#"token"];
[manager POST:[BaseURLString stringByAppendingString:methodName] parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject){
NSLog(#"JSON: %#", responseObject);
UserDict=responseObject;
[self.TableviwSideMenu reloadData];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error){
NSLog(#"Error: %#", [error localizedDescription]);
[self showAlert: [error localizedDescription]];
}];
the AFNetworking will do the serialization for you and the responseObject will most likely be either a NSArray or NSDictionary object do like
[manager POST:[BaseURLString stringByAppendingString:methodName] parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject){
NSLog(#"JSON: %#", responseObject);
if ([responseObject isKindOfClass:[NSArray class]]) {
NSArray *responseArray = responseObject;
UserDict=responseArray;
/* do something with responseArray */
} else if ([responseObject isKindOfClass:[NSDictionary class]]) {
NSDictionary *responseDict = responseObject;
UserDict=responseDict;
/* do something with responseDict */
}
if (UserDict.count>0)
[self.TableviwSideMenu reloadData];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error){
NSLog(#"Error: %#", [error localizedDescription]);
[self showAlert: [error localizedDescription]];
}];
The AFNetworking framework and its delegate will handle everything. You will get responseObject in NSDictionary.
-(void)Request{
[self.Request_coursecomplete setRequestMethod:#"POST"];
self.Request_coursecomplete = [ASIFormDataRequest requestWithURL:sendSMSURL];
self.Request_coursecomplete.delegate = self;
//will try second time
[self.Request_coursecomplete setNumberOfTimesToRetryOnTimeout:2];
[self.Request_coursecomplete setShouldContinueWhenAppEntersBackground:YES];
NSTimeInterval timeOutSecs = 60000;
[self.Request_coursecomplete setTimeOutSeconds:timeOutSecs];
[self.Request_coursecomplete startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSString *receivedString = [request responseString];
NSLog(#"json string: %#",receivedString);
NSDictionary *d = [receivedString JSONValue];
}
I'm currently learning blocks, and I want to use them with AFNetworking. I made method in Singletone:
- (void)getAllPlayers:(void (^)(NSArray *playerz, bool succeed))blockPlayers {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:#"https://api.myjson.com/bins/530re" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
I called this method in viewDidLoad:
[[Manager sharedInstance]getAllPlayers:^(NSArray *playerz, bool succeed) {
if (succeed == YES) {
self.allClubs = playerz;
[self.tableView reloadData];
}
}];
But nothing is downloaded.
Yo forgot to call the blockPlayers Completion handler.
- (void)getAllPlayers:(void (^)(NSArray *playerz, bool succeed))blockPlayers {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:#"https://api.myjson.com/bins/530re" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSarray *returnedPLayerz = [NSArray array];
//Here treat operation and response Object to extract playerz and assing it to returnedPlayerz
blockPLayers(returnedPlayerz, YES);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
blockPlayers(nil, NO);
NSLog(#"Error: %#", error);
}];
}
You got data from server in response object. After that you need to parse it and return in block:
- (void)getAllPlayers:(void (^)(NSArray *playerz, bool succeed))blockPlayers {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:#"https://api.myjson.com/bins/530re" parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSArray* players = [self getPlayersFromJson:responseObject];
blockPlayers(players, YES);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
blockPlayers(nil, NO);
}];
}
So you need to create parser method getPlayersFromJson
this is always error with -1004 ( could not connect to server )
but the request in browser is working fine.
what's wrong with my code?
(url : "http://localhost:3000/v1/voice/version?appname=wevoice")
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager GET:#"http://localhost:3000/v1/voice/version"
parameters:#{ #"appname": #"wevoice" }
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
You have to set the property baseURL on your request manager. Here is an example:
self.requestManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:http://localhost:3000];
Later, in your concrete GET message to the manager, you'll only pass the relative URL path:
[self.requestManager GET:#"/v1/voice/version"
parameters:#{ #"appname": #"wevoice" }
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
And keep in mind, that, if you want to send your paramters as JSON, you'll need a request serializer:
self.requestManager.requestSerializer = [AFJSONRequestSerializer serializer];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setObject:#"wevoice" forKey:#"appname"];
[manager GET:#"http://localhost:3000/v1/voice/version"
parameters:dic
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
You can try this.May be the way you add Parameter is wrong.
Try this method. Hope it helps.
+ (void)getRequestWithURLStringWithSuccess:(void(^)(id object))successBlock andFail:(void(^)(NSString *errorMessage))failBlock {
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc]initWithBaseURL:[NSURL URLWithString:#"http://localhost:3000/v1/voice/version"]];
NSString *urlString = #"/version";
[manager GET:urlString parameters:#{ #"appname": #"wevoice" } success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
I'm using AFNetworking for some GET queries. But my function always returns nil value. Where I was wrong?
+ (NSString *)getRequestFromUrl:(NSString *)requestUrl {
NSString * completeRequestUrl = [NSString stringWithFormat:#"%#%#", BASE_URL, requestUrl];
__block NSString * results;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:completeRequestUrl parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
results = [NSString stringWithFormat:#"%#", responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
results = [NSString stringWithFormat:#"Error"];
}];
NSLog(#"%#", results);
return results;
}
Thx! Artem.
You're not seeing a result because the blocks that you pass in for success and failure run asynchronously; by the time your NSLog gets called, the web service won't have returned yet. If you move your NSLog inside of your success and failure blocks, you should see a result get output to your console.
Because of the asynchronous nature of these calls, you won't be able to simply return the value from your method. Instead, you may want to take your own block as a parameter, which you can then call when you have a result. For example:
+ (void)getRequestFromUrl:(NSString *)requestUrl withCompletion:((void (^)(NSString *result))completion
{
NSString * completeRequestUrl = [NSString stringWithFormat:#"%#%#", BASE_URL, requestUrl];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:completeRequestUrl parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *results = [NSString stringWithFormat:#"%#", responseObject];
if (completion)
completion(results);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSString *results = [NSString stringWithFormat:#"Error"];
if (completion)
completion(results);
}];
}
You would then call your method like so:
[YourClass getRequestFromUrl:#"http://www.example.com" withCompletion:^(NSString *results){
NSLog(#"Results: %#", results);
}
AFNetworking's sample project has an example of using a block parameter to return a value from your web service calls: https://github.com/AFNetworking/AFNetworking/blob/master/Example/Classes/Models/Post.m
- (void)POST:(NSString *)URLString
parameters:(id)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
[_manager POST:[NSString stringWithFormat:#"%#%#",API_HOST,URLString] parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
block(formData);
} progress:^(NSProgress * _Nonnull uploadProgress1) {
uploadProgress(uploadProgress1);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
success(task,responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
failure(task,error);
}];
}