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);
}];
}
Related
I think its been very simple question, but i'm stuck to it quite long time. I have a function but getting some brackets issue and unable to run the code. I'm not getting where the brackets should close.
My code is,
-(void)Images{
NSString *eachImagePath;
if(_arrai.count == 0)
return;
eachImagePath = [NSString stringWithFormat:#"%#",_arrai[0]];
NSMutableDictionary *dictAddNewJobImages = [[NSMutableDictionary alloc]init];
dictAddNewJobImages[#"property_id"] = Propid;
dictAddNewJobImages[#"name"] = _arrainame;
NSString *strWebService = [NSString stringWithFormat:#"My URL"];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer.acceptableContentTypes=[NSSet setWithObject:#"text/html"];
[manager.requestSerializer setTimeoutInterval:600.0];
[manager POST:strWebService parameters:dictAddNewJobImages constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData)
{
NSURL *filePath = [NSURL fileURLWithPath:eachImagePath];
[formData appendPartWithFileURL:filePath name:#"image" error:nil];
} progress:^(NSProgress * _Nonnull uploadProgress)
{
} success:^(NSURLSessionDataTask* _Nonnull *task, id _Nullable responseObject)
{
NSLog(#"%#",responseObject);
[_arrai removeObjectAtIndex:0];
if(_arrai.count > 0)
[self Images];
} failure:^(NSURLSessionDataTask* _Nullable task, NSError* _Nonnull error) {
NSLog(#"%#",error);
}
}
you forget to close your block }];
use
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:XXXXXX parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(#"Error: %#", error);
}]; --> add the close in failure
instead of
[manager GET:XXXXXX parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(#"Error: %#", error);
}
updated answer
-(void)Images{
NSString *eachImagePath;
if(_arrai.count == 0)
return;
eachImagePath = [NSString stringWithFormat:#"%#",_arrai[0]];
NSMutableDictionary *dictAddNewJobImages = [[NSMutableDictionary alloc]init];
dictAddNewJobImages[#"property_id"] = Propid;
dictAddNewJobImages[#"name"] = _arrainame;
NSString *strWebService = [NSString stringWithFormat:#"My URL"];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer.acceptableContentTypes=[NSSet setWithObject:#"text/html"];
[manager.requestSerializer setTimeoutInterval:600.0];
[manager POST:strWebService parameters:dictAddNewJobImages constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData)
{
NSURL *filePath = [NSURL fileURLWithPath:eachImagePath];
[formData appendPartWithFileURL:filePath name:#"image" error:nil];
} progress:^(NSProgress * _Nonnull uploadProgress)
{
} success:^(NSURLSessionDataTask* _Nonnull *task, id _Nullable responseObject)
{
NSLog(#"%#",responseObject);
[_arrai removeObjectAtIndex:0];
if(_arrai.count > 0)
[self Images];
} failure:^(NSURLSessionDataTask* _Nullable task, NSError* _Nonnull error) {
NSLog(#"%#",error);
}]; -- > close your block here
}
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 Have Used the following method to convert data to dictionary in my App but it shows json object was nil.
It's printing "jsonObject is null".
Is there any problem with "error:nil".
- (void)postNonceToServer:(NSString *)paymentMethodNonce {
// Update URL with your server
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
NSDictionary *parameters = #{#"payment_method_nonce":paymentMethodNonce,#"amount":amountStr,#"tripid":tripIdStr,#"currencycode":currencyStr};
[manager POST:#"http:url.php" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
//NSArray *response = responseObject;
//response = responseObject;
NSLog(#"responseObject is %#",responseObject);
jsonObject=[NSJSONSerialization
JSONObjectWithData:responseObject
options:NSJSONReadingMutableLeaves
error:nil];
NSLog(#"jsonObject is %#",jsonObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
Here, I am using AFNetworking 3.0. So i will give you "POST" method code in AFNetworking 3.0 version.
Step 1 :- Create one NSObject Class and write down this method in .h file.
+ (void)requestPostUrl: (NSString *)serviceName parameters:(NSDictionary *)dictParams success:(void (^)(NSDictionary *responce))success failure:(void (^)(NSError *error))failure;
Step 2 :- Write down this code in .m file
here "kBaseURL" means Web service URL and "serviceName" name of service.
+ (void)requestPostUrl: (NSString *)serviceName parameters:(NSDictionary *)dictParams success:(void (^)(NSDictionary *responce))success failure:(void (^)(NSError *error))failure {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[manager.requestSerializer setQueryStringSerializationWithBlock:^NSString * _Nonnull(NSURLRequest * _Nonnull request, id _Nonnull parameters, NSError * _Nullable __autoreleasing * _Nullable error) {
//Here your data converting in JSON.
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:error];
NSString *argString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
return argString;
}];
NSString *strService = [NSString stringWithFormat:#"%#%#",kBaseURL,serviceName];
[manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
//[SVProgressHUD showWithStatus:#"Please wait..."];
[SVProgressHUD show];
[manager POST:strService parameters:dictParams progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if([responseObject isKindOfClass:[NSDictionary class]]) {
if(success) {
[SVProgressHUD dismiss];
success(responseObject);
}
}
else
{
NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:nil];
if(success) {
[SVProgressHUD dismiss];
NSLog(#"POST Response : %#",response);
success(response);
}
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if(failure) {
[SVProgressHUD dismiss];
failure(error);
}
}];
}
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
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);
}];