I've implemented the JSON parsing using AFNetworking many time in some previous apps as:
NSString *string = [NSString stringWithFormat:#"%#?get_all_data", BaseURLString];
NSURL *url = [NSURL URLWithString:string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
//performing parsing here
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//error message displayed here
}
But as of today I started working on an app after a while I came to use AFNetworking again and I installed in using pods so as I write this same code as I use to write before it gives me the error saying Unknown Receiver AFHTTPRequestOperation. Do you mean AFHTTPRequestSerializer?
After searching about it I found that it's AFNetworking 2 or 3 era now and they have somehow changed the scenerio. I didn't find the exact solution on how to implement it now. So can anyone write the code in the answer below that works with the latest version of AFNetworking.
This is the new approach of AFNetworking 3.x to parse data:
NSString *path = #"yourapilink";
NSString *escapedPath = [path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:escapedPath parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Hope it help !
Related
I have a few requests that needs to fire one by one while depending on the previous response.
That was pretty straight forward with NSOperation and trying to figure out
what's the best approach here with Sessions & AFNetworking >= 3.0
-(void)startGet
{
NSString *urlStr = [NSString stringWithFormat:#"https://test.com/test?%ld",(long)test];
NSURL *URL = [NSURL URLWithString:urlStr];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSLog(#"NUMBER: %ld",(long)test);
[manager GET:URL.absoluteString parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSLog(#"task: %#",task.currentRequest.URL.absoluteString);
} failure:^(NSURLSessionTask *operation, NSError *error) {
//NSLog(#"Error: %#", error);
}];
}
- (void)viewDidLoad {
[super viewDidLoad];
for (int i=0; i<10; i++)
{
test = i;
[self startGet];
}
}
The log I want to get is:
https://test.com/test?0
https://test.com/test?1
https://test.com/test?2
https://test.com/test?3
https://test.com/test?4
https://test.com/test?5
https://test.com/test?6
...
Things I've tried:
...
dispatch_group_t serviceGroup = dispatch_group_create();
...
-(void)startGet
{
NSString *urlStr = [NSString stringWithFormat:#"https://test.com/test?%ld",(long)test];
NSURL *URL = [NSURL URLWithString:urlStr];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSLog(#"NUMBER: %ld",(long)test);
dispatch_group_enter(serviceGroup);
[manager GET:URL.absoluteString parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSLog(#"task: %#",task.currentRequest.URL.absoluteString);
dispatch_group_leave(serviceGroup);
} failure:^(NSURLSessionTask *operation, NSError *error) {
dispatch_group_leave(serviceGroup);
//NSLog(#"Error: %#", error);
}];
dispatch_group_wait(serviceGroup,DISPATCH_TIME_FOREVER);
}
Although the request came out in the right order I would still get mixed responses like so:
https://test.com/test?4
https://test.com/test?7
https://test.com/test?1
https://test.com/test?3
I'm not sure if something is wrong with the code or I totally misunderstood the purpose of dispatch_group_t in that case.
I've digged around and saw a comment by matt from AFNetworking about integrating a simple solution using Operations & session in AF and it is soon to be public but it was over 2 years ago.
I'm trying to solve this without using nested requests or NSOperations
Thanks
You can try out 2 approaches
Semaphore
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSLog(#"NUMBER: %ld",(long)test);
[manager GET:URL.absoluteString parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
dispatch_semaphore_signal(semaphore);
NSLog(#"task: %#",task.currentRequest.URL.absoluteString);
} failure:^(NSURLSessionTask *operation, NSError *error) {
//NSLog(#"Error: %#", error);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
WaitUntillFinished
[operation waitUntilFinished];
You can check for detailed implementation at below link:
https://github.com/AFNetworking/AFNetworking/issues/1804
I'm learning to use AFNetworking and do a GET request.
AFNetworking (3.1.0)
XCode 6
Code:
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:#"http://localhost:5000/index" parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(#"Error: %#", error)p;
}];
However, I got the error
Incompatible block pointer types sending 'void (^)(NSURLSessionTask *__strong, NSError *__strong)' to parameter of type 'void (^ __nullable)(NSURLSessionDataTask * __nonnull __strong)'
Tried many times but couldn't figure out why?
Finally I find out that the problem really is the wrong version Xcode. In Xcode 6 it doesn't recognize nullable. Upgrading my Xcode just solved the problem.
i think your parameter value don't send nil values, I am also using afNetworking Get method, please refer below code,
viewDidLoad give below code:
NSURL *url = [NSURL URLWithString:#"http://localhost:5000/index"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//AFNetworking asynchronous url request
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
movies = [responseObject objectForKey:#"enquiry"];
NSSortDescriptor *titleSort = [[NSSortDescriptor alloc] initWithKey:#"FirstName"
ascending:YES selector:#selector(caseInsensitiveCompare:)];
// NSMutableArray *sortDescriptors = [[NSMutableArray alloc] initWithObjects: titleSort, nil];
movies=[NSMutableArray arrayWithArray:[movies sortedArrayUsingDescriptors:#[titleSort]]];
NSLog(#"The Array: %#",movies);
[self.mytableView reloadData];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Request Failed: %#, %#", error, error.userInfo);
}];
[operation start];
don't forget #import "AFNetworking.h" in header
hope its helpful
I'm using AFNetworking in my iOS project, and this is my code:
NSURL *url = [NSURL URLWithString: [signinUrl stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager POST:signinUrl parameters:dicParam success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSString *myString = [[NSString alloc] initWithData:operation.request.HTTPBody encoding:NSUTF8StringEncoding];
NSLog(#"Error: %#", myString);
}];
This code let to make connection with server correctly and I receive an answer, but I need to catch the code status with their description, I mean... catch something like that:
status_code: 406 custom message
I can get status code but it is an integer, anyone have idea how I can get this custom message?
I am trying to use AFHTTPRequestOperationManager to make an HTTP request. I need to use AFHTTPRequestOperationManager because I want to be able to cancel all operations if necessary. I can't get this working for some reason. The completion blocks aren't called. Am I missing something?
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://twitter.com/%#", username]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:#"MyUserAgent (iPhone; iOS 7.0.2; gzip)" forHTTPHeaderField:#"User-Agent"];
[request setHTTPMethod:#"GET"];
[self.manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *html = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
if ([html containsString:#"var h = decodeURI(l.hash.substr(1)).toLowerCase();"]) {
completion(YES, nil);
} else {
completion(NO, nil);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
completion(NO, error);
}];
This is working code, you need to use GET or POST method there.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = #{#"email":emailfield.text};
[manager GET:#"http://example.com/api" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
While everyone else is right -- you should be using the modern AFNetworking constructs instead of the legacy features -- there is a quick way to get done what you're looking to get done.
By the looks of it, the method - (??? *) HTTPRequestOperationWithRequest:success:failure likely returns an AFHTTPRequestOperation. If I'm correct, you just need to actually start the operation. See below for your code, corrected.
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://twitter.com/%#", username]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:#"MyUserAgent (iPhone; iOS 7.0.2; gzip)" forHTTPHeaderField:#"User-Agent"];
[request setHTTPMethod:#"GET"];
AFHTTPRequestOperation *op = [self.manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *html = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
if ([html containsString:#"var h = decodeURI(l.hash.substr(1)).toLowerCase();"]) {
completion(YES, nil);
} else {
completion(NO, nil);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
completion(NO, error);
}];
[op start];
HTTPRequestOperationWithRequest method returns AFHTTPRequestOperation. You have to add it to some operation queue to start it. For example
AFHTTPRequestOperation *operation = [self.manager HTTPRequestOperationWithRequest:request .........
[[NSOperationQueue currentQueue] addOperation:operation];
You can use AFHTTPSessionManager which is a little better than AFHTTPRequestOperationManager and cancel requests using method cancel of NSURLSessionDataTask. You can find some code examples here - AFNetworking 2.0 cancel specific task
Check this will work
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:#"application/json", nil];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager POST:url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
I'm using the following code to set up my operation manager:
requestSerializerJson = [AFJSONRequestSerializer serializer];
[requestSerializerJson setValue:[taskHandler getBranchesApiConstantForName:#"header_value_content_type"] forHTTPHeaderField:[taskHandler getBranchesApiConstantForName:#"header_name_content_type"]];
[requestSerializerJson setValue:[taskHandler getBranchesApiConstantForName:#"header_value_api_key"] forHTTPHeaderField:[taskHandler getBranchesApiConstantForName:#"header_name_api_key"]];
httpRequestOperationManager = [AFHTTPRequestOperationManager manager];
httpRequestOperationManager.requestSerializer = requestSerializerJson;
httpRequestOperationManager.responseSerializer = [AFJSONResponseSerializer serializer];
httpRequestOperationManager.operationQueue = [[NSOperationQueue alloc] init];
httpRequestOperationManager.operationQueue.maxConcurrentOperationCount = 1;
Then, I've got a method to download multiple JSON strings:
- (void)downloadBranches {
NSLog(#"Test %#", httpRequestOperationManager.requestSerializer.HTTPMethodsEncodingParametersInURI);
for (NSString *branchUuid in taskHandler.addedBranchesUuids) {
NSString *urlString = [NSString stringWithFormat:#"%#%#%#", urlBase, [taskHandler getBranchesApiConstantForName:#"getbranch_suffix"], branchUuid];
NSURL *URL = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSLog(#"Test %#", request.allHTTPHeaderFields);
AFHTTPRequestOperation *op = [httpRequestOperationManager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[httpRequestOperationManager.operationQueue addOperation:op];
}
}
All the operations are performed but I get a message from the server which says that I didn't supply the authentication key.
I specifically set it in the 3rd line - for the requestSerializerJson which is then added to the httpRequestOperationManager so all of the requests should be using the headers.
I added an NSLog to print request.allHTTPHeaderFields but it says "(null)".
How can I fix this?
downloadBranches is completely bypassing the serializer by building an NSURLRequest manually. The whole point of the serializer is to do that for you.
You need to call requestWithMethod:URLString:parameters: on your serializer, which will return an NSURLRequest with the headers you want.
Or just use the operation manager's GET:… method inside that for loop; your use case doesn't look like it requires this other stuff at all.