AFNetworking synchronous request - objective-c

I want to use AFNetworking http client synchronously. I am not sure how to go about this. The reason i choose to do it this way is because i am making a server call on the click of a button. I dont want the user to interact with the UI until I am done processing the response. Sample code would be extremely helpful.

Don't. Just Don't.
In the user side it would freez everything and make your app feel buggy.
At least you can use asynchronous request and a loader like that : https://github.com/samvermette/SVProgressHUD
Exemple :
[SVProgressHUD show];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"https://gowalla.com/users/mattt.json"]];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
[SVProgressHUD dismiss];
} failure:nil];

Related

How To Use AFNetworking On Background Thread?

I have an app currently using AFNetworking 1.0 to sync data from a REST Web Service.
When the sync occurs currently by tapping a button on the UI it blocks the UI.
I'm upgrading the app to use AFNetworking 2.0.
How can I make the sync happen on a background thread so the UI does not stall?
Did you try this:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"https://gowalla.com/users/mattt.json"]];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"Name: %# %#", [JSON valueForKeyPath:#"first_name"], [JSON valueForKeyPath:#"last_name"]);
} failure:nil];
Check the following link
https://github.com/AFNetworking/AFNetworking/wiki/Introduction-to-AFNetworking

canceling all operations in AFImageRequestOperation

I'm using AFImageRequestOperation to download hundreds of jpg from my server.
NSURLRequest *request = [NSURLRequest requestWithURL:theURL cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:20];
AFImageRequestOperation *operation;
operation = [AFImageRequestOperation imageRequestOperationWithRequest:request
imageProcessingBlock:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {}
];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:[[paths objectAtIndex:0] stringByAppendingPathComponent:picture] append:NO];
[downloadQueue addOperation:operation];
If I now want to cancel the download in progress I execute [downloadQueue cancelAllOperations].
With the previous version of AFNetworking that I used (earlier this year) this worked perfectly but with the recent one I get this:
ERROR [http://myImageURL] -- The operation couldn’t be completed. (NSURLErrorDomain error -999.)
for all pending operations.
Do I have to to do some additional stuff now?
In NSURLErrorDomain, that error code is defined as follows:
kCFURLErrorCancelled = -999
...which makes sense, since the operation was indeed cancelled. This is not a bug, but an expected behavior. The change may be either a documented change to AFNetworking, or an undocumented one in NSURLConnection between iOS versions.

Reload UITableView data and not the visible cells

I'm working on an app where I want to pull data from a remote web service and populate a UITableView. When I get new data I want the currently visible cells to remain and add the new data above it, much like most Twitter clients does. My load method currently looks like this:
- (void)loadPostsInBackground
{
NSURL *url = [NSURL URLWithString:#"[URL]"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation;
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id jsonObject) {
[self createPostsFromDict:jsonObject];
[self.refreshControl endRefreshing];
[self.tableView reloadData];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id jsonObject) {
NSLog(#"Received an HTTP %d", response.statusCode);
NSLog(#"The error was: %#", error);
}];
[operation start];
}
This works, but it updates the currently visible cells with the new data. So what I want is, get new data, add it above the currently visible cells (or stay at the currently visible cells). What is the best way to do this?
Note: I will require iOS6.
Instead of calling reloadData on the table view. You should call insertRowsAtIndexPaths:withRowAnimation:. Do that after updating the data used by the table view's data source.

AFNetworking PUT and Delete with Rails

In looking at the AFNetworking documentation, the Put and Delete methods take in a path and a dictionary of parameters. I am using Rails as my backend which expects these two types to take the form of Put /object/1.json and Delete /object/1.json. Should I build up a path string by adding in the Id or do I send a Put or Delete with the Id as one of the params in the Dictionary?
Typically when I do with PUT and similar type HTTP requests when using AFNetworking is something like this:
// Create an HTTP client with your site's base url
AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:#"http://example.com"]];
// Setup the other parameters you need to pass
NSDictionary *parameters = #{#"username" : #"bob", #"password" : #"123456"};
// Create a NSURLRequest using the HTTP client and the path with your parameters
NSURLRequest *request = [client requestWithMethod:#"PUT" path:#"object/1.json" parameters:parameters];
// Create an operation to receive any response from the server
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// Do stuff
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
// Handle error
}];
// Begin the operation
[operation start];
If you look in AFHTTPClient.h there are examples for how to format your base url and your paths. There's more information on these methods in the AFNetworking documentation

AFImageRequestOperation wait until finished

i have a little problem with this, I'm loading an Image from a Url like this:
+ (void)getImageFromURL:(NSString *)imageFilename urlMode:(NSString *)mode block:(id (^)(UIImage *responseImage))aImage {
NSURL *url = [NSURL URLWithString:[mainURL stringByAppendingString:mode]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
AFImageRequestOperation *requestOperation = [AFImageRequestOperation imageRequestOperationWithRequest:request
imageProcessingBlock:nil
cacheName:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image)
{
aImage(image);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error)
{
// manage errors
}];
[[[NSOperationQueue alloc]init] addOperation:requestOperation];
}
I'm trying to set an iVar UIImage *userAvatar to the response from this request, but the problem is, since its an async request I'm not getting the iVar set before my Code moves on, so my iVar is empty when I'm accessing it and passing it to another method.
That's the nature of asynchronous programming! You are going to have to redesign the dependencies on userAvatar to take into account that it's availability is nondeterministic.
So, rather than having your operation's success block simply set the userAvatar ivar, it takes care of whatever needs to happen once that image is available. For example if you want to set a UIImageView's image, then in your success block:
dispatch_async(dispatch_get_main_queue(), ^{
myImageView.image = image;
});
(Without knowing the details of your goals and details of your implementation, this is just a "for example...")
You forgot to add [requestOperation start]; at the end.