I'm new to IOS development and was doing something related to dynamic data request through a 3rd party api using AFNetworing, I assume this is the good way to do networking in IOS?
One issue I have so far is I have two AFHTTPSessionManager in two different class implementation files. When I ran the application, the first one executes successfully. but the second one is not working and the problem is in debug mode, I can see that the
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:PLACE_DETAIL_URL
parameters:#{ #"key": APPLICATION_KEY,
#"placeid": placeid,
#"extensions": #"review_summary"
}
success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(#"%#", responseObject);
placeDetail = [[NSDictionary alloc] initWithDictionary: (NSDictionary *) [responseObject objectForKey:#"result"]];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error Places"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
}];
is not even executing. It's been skipped for some reason. Is this a bug or I can only have on AFHTTPSessionManager or AFHTTPOperationManager at a time?
P.S.
debug gif posted here for clear idea.
thanks for all your help.
Related
I am trying to check if my POST request is working properly using AFNetworking in Objective c. Request is working fine in Android and Postman. Here is my URL:
#define API_BASE #"54.191.xx.xxx/XXXXXXXX/index.php/checkout"
Here are my params:
NSDictionary *paramters = #{#"quantity":#"21", #"price":#"10"};
This is my code to make the request:
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"application/json"];
[manager POST:API_BASE parameters:paramters progress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(#"%#",responseObject);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Error" message:error.localizedDescription delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}];
This code never enters the success block and I am getting an error saying 'Unsupported URL'. Any help would be appreciated.
Change API_BASE value to include http://:
#define API_BASE #"http://54.191.26.206/EntropikSDKBackend/index.php/checkout
54.191.xx.xxx/XXXXXXXX/index.php/checkout is not a valid URL. You need to specify the scheme. Likely http:// or https://.
Note: http and https are the schemes. :// is just part of the URL syntax.
You will need to add http:// to your API_BASE, like so:
#define API_BASE #"http://54.191.26.206/EntropikSDKBackend/index.php/checkout
You will most likely also need to add an ATS exception to your info.plist to allow unencryped traffic to the host 54.191.26.206
You are missing the network reference path. Any URL you are providing should also need the network reference path for communication and to decide which scheme/protocol need to be used.
I am using AFNetworking framework to call the web service and i have used
POST method to get response from the web service like that :
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setTimeoutInterval:25];
[manager POST:stringURL parameters:param
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"RESPONCE : %#", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#", error);
NSString *msg = error.localizedDescription;
UIAlertView *alertview = [[UIAlertView alloc]initWithTitle:#"That Shift" message:msg delegate:nil cancelButtonTitle:#"Dissmiss" otherButtonTitles:nil, nil];
[alertview show];
}];
NSLog(#"Right AFter Block Execution RESPONCE : %#", responseObject);
i want my response right after its execution in NSLog(#"Right AFter Block Execution RESPONCE : %#", responseObject); can any one suggest me how can i do that ?
REASON BEHINDE DOING THAT :
The reason behind doing that is i want to use another block right after that code which i have given and i want to use that responce in second block which will be right after that in the plce of NSLog(#"Right AFter Block Execution RESPONCE : %#", responseObject);.
You can use semaphores to synchronize your threads, so the first thread will block and wait for second. But do not do it on main thread since your GUI will freeze.
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
// Inside callback:
dispatch_semaphore_signal(sema);
// Before NSLOG
dispatch_semaphore_wait(sema, <timeout_may_be_forever>);
I have a class method containing a block, of AFNetworking in which i want to return one dictionary variable, code shown below:
+(NSMutableDictionary*) getFromUrl:(NSString*)url parametersPassed:(NSDictionary*)parameters;
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
__block NSMutableDictionary *resultarray;
[manager GET:url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"JSON: %#", responseObject);
NSMutableDictionary *resultarrayTwo = (NSMutableDictionary *)responseObject;
resultarray = resultarrayTwo;
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#, %#", error, operation.responseString);
UIAlertView *alertView=[[UIAlertView alloc] initWithTitle:#"Message" message:#"Try again" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alertView show];
}];
return resultArray;
}
How can i return resultArray here, it returns nothing here due to the difference in control flow.
I don't have much knowledge in Objective C block. Waiting for your help.
Thank you.
Change your function design to the following function using Completion Blocks
+(void)getFromUrl:(NSString*)url parametersPassed:(NSDictionary*)parameters completion:(void (^) (NSMutableArray *values))completion;
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"JSON: %#", responseObject);
NSMutableDictionary *resultarray = (NSMutableDictionary *)responseObject;
completion(resultarray);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#, %#", error, operation.responseString);
UIAlertView *alertView=[[UIAlertView alloc] initWithTitle:#"Message" message:#"Try again" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alertView show];
completion(nil);
}];
}
And call the function
[YourClass getFromUrl:url parametersPassed:params completion:^(NSMutableArray *values) {
NSLog(#"%#",values);
}];
Update
Removed the extra array used.
Hope this helps.
The network call is asynchronous in nature, so having this method return its result isn't probably the right way of thinking as it implies you do a synchronous network call.
Have the method take a block parameter instead, and execute that block with the result at a later point of time from the AFNetworking completion block.
Before getting the response for GET call, it will execute the next lines. Thats why you are getting no data into Array.
You can call delegate method in success and failure block. This is the best solution.
I am creating an iOS Application working in offline mode by using a AFNetworking library.
To manage a HTTP request I have defined a AFHTTPRequestOperationManager
- (AFHTTPRequestOperationManager *)requestOperationManager
{
if (!_requestOperationManager)
{
_requestOperationManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:SERVICE_BASE_URL]];
}
return _requestOperationManager;
}
To load a HTTP request I have defined a method:
- (void)loadRequest
{
if (!self.internetConnectionAvaliable)
{
self.requestOperationManager.requestSerializer.cachePolicy = NSURLRequestReturnCacheDataElseLoad;
}
NSString *url = SERVICE_METHOD_URL;
NSDictionary *parameters = #{#"password" : USER_PASSWORD, #"username" : USER_NAME};
[self.requestOperationManager POST:url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSString *htmlString = [NSString stringWithFormat:#"%#", [responseObject objectForKey:#"view"]];
[self.webView loadHTMLString:htmlString baseURL:nil];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"ERROR!!!" message:#"ERROR!!!" delegate:nil cancelButtonTitle:#"CANCEL" otherButtonTitles:nil];
[alertView show];
}];
}
When internet connection is enabled, AFNetworking loads desired data perfectly.
When internet connection is disabled, AFNetworking doesn't load any data. This makes me think, that data caching doesn't work as it should!
Does anyone knows why?
How to fix it?
I have a Django Rest Api with a iOS app and right now I'm testing AFNetworking to change the HTTP Request my app is doing but i came with this dilema that i dont know how to handle, first is that on REST Standards when i get an error i should return a 404_BAD_REQUEST as a status if either sends or something wrong happens and this is OK. The issue comes when AFNetworking sees this 404. I still want to see the JSON that it returns.
curl -X POST http://domain.com:8000/user-login/ -d "nick=superUser&pass_field=superPassword"
i get 202 Status HTTP:
{
"nick": "eddwinpaz", "rate": 30, "name": "Eddwin Paz", "avatar": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-prn2/t1.0-1/p160x160/10270540_10154074250190063_1762683854515424400_n.jpg", "id": 9}eddwinpazs-MacBook-Pro:~ eddwinpaz$
}
When i get 404 BAD REQUEST i get:
{"message": "Invalid Username or Password"}
I want to grab that message json tag if i get a 404 Error
I've the following code. and put it on the message on the Alert
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"nick": #"eddwinpaz",#"pass_field":#"eddwinpaz1"};
AFHTTPRequestOperation *operation = [manager POST:#"http://domain.com/user-login/"];
[operation addAcceptableStatusCodes:[NSIndexSet indexSetWithIndex:404]];
[manager POST:#"http://domain.com/user-login/" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Login Failed"
message:#"E-mail or password are wrong, Please Try Again"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[hud hide:YES];
}];
Per default the error code 404 is handled as an error code. You could add it as one of the accepted error codes via
AFHTTPRequestOperation *operation = [manager POST:#"http://doma...
[operation addAcceptableStatusCodes:[NSIndexSet indexSetWithIndex:404]];
Then success: is called on an 404 response and you can handle it there.
The answer by #miho did not work for me. addAcceptableStatusCodes does not exist in AFNetworking 2.5.0 from what I can tell. I had to do the following.
NSMutableIndexSet *acceptedCodes = [[NSMutableIndexSet alloc]
initWithIndexSet:operation.responseSerializer.acceptableStatusCodes];
[acceptedCodes addIndex:304];
operation.responseSerializer.acceptableStatusCodes = [acceptedCodes copy];