I'm relatively new to AFNetworking and would like to find a better solution for the following problem.
I am using 2 AFJSONRequestOperations at the start of my iOS application.
AFJSONRequestOperation *operation1 = [AFJSONRequestOperation JSONRequestOperationWithRequest:request1 success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// do something
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON, NSError *error){
// do something
}];
AFJSONRequestOperation *operation2 = [AFJSONRequestOperation JSONRequestOperationWithRequest:request2 success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// do something
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON, NSError *error) {
// do something
}];
[operation1 start];
[operation2 start];
I wait for both operations to finish and start further processing.
I thought I can combine both of this operations into the enqueueBatchOfHTTPRequestOperationsWithRequests method.
AFHTTPClient *client = [[AFHTTPClient alloc] init];
NSArray *requests = [NSArray arrayWithObjects:operation1, operation2, nil];
[client enqueueBatchOfHTTPRequestOperationsWithRequests:requests progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
// track operations
}completionBlock:^(NSArray *operations) {
// do something
}];
So I would like to track the finished operations and execute the completion block for each operation separatly. Is it something I can perform with AFHTTPClient?
Related
Is that possible to rewrite following code used AFNetworking v 1.6:
__block AFJSONRequestOperation *operation =
[AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
[self uploadFinished:JSON completionBlock:completion failureBlock:failure];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
[self uploadFailedWithError:error completionBlock:completion failureBlock:failure];
[UIApplication hideProgressLoading];
}];
[operation
setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
[UIApplication updateProgress:totalBytesWritten * 1.0/totalBytesExpectedToWrite];
}];
[operation start];
to the AFNetworking 3.1 version?
I'm trying to use AFNetworking to call a Rest API but I'm not getting the proper response string. This is my code:
NSURL *url = [[NSURL alloc] initWithString:#"https://www.ez-point.com/api/v1/ezpoints"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"%#",#"testing");
NSLog(#"%#",operation.responseData);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"%#", #"Error");
}];
[operation start];
but I'm getting this as print out:
2013-10-29 08:31:08.175 EZ-POINT[4004:c07] testing
2013-10-29 08:31:08.175 EZ-POINT[4004:c07] (null)
As you can see, it is returning null, I was expecting this:
{"status": "user_invalid", "data": "", "token": "", "errors": ["user not found"], "user_id": ""}
I'm more accustomed to this way of setting up the request:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"https://www.ez-point.com/api/v1/ezpoints"]];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"%#",#"testing");
NSLog(#"%#",operation.responseData);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"%#", #"Error");
}];
[operation start];
I am implementing a code that downloads images and saves them in the database of the app,
I have an array of objects, each object contains the image url and some other information. To Download the images I'm using the class library AFImageRequestOperation.h AFNetworking.
My code downloads and saves the data in the database, but need to notify the user which image is downloaded, eg: if I have an array containing 5 objects (quoted just above what each object), will have to do downloading the same order that is in the array, but as AFImageRequestOperation makes downloading asynchronously item 4 can be downloaded before the first item.
In short, I want to have control and only release for the next download when the previous one is completed.
I have a for that runs through the array of objects and calls a function for each position, the function has the following code:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[arrImagem valueForKey:#"urlimagem"]]];
AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request imageProcessingBlock:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image){
Imagens *imagem = (Imagens *)[NSEntityDescription insertNewObjectForEntityForName:#"IMAGENS" inManagedObjectContext:managedObjectContext];
// Save Image
NSData *imageData = UIImageJPEGRepresentation(image, 90);
[imagem setCategoria:cat];
[imagem setTitulo:[arrImagem valueForKey:#"titulo"]];
[imagem setDescricao:[arrImagem valueForKey:#"descricao"]];
[imagem setImagem:imageData];
NSError *error;
if(![managedObjectContext save:&error]){
NSLog(#"houve um erro muito grave");
//return false;
}else{
NSLog(#"Salvou imagem");
}
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){
NSLog(#"%#", [error localizedDescription]);
}];
[operation start];
I do not know if my question was very clear, but basically my question is similar to this link
AFImageRequestOperation is a subclass of NSOperation so you can use:
- (void) addDependency: (NSOperation*) operation
to make sure that one operation finishes before the other.
For example:
NSOperation *op1 = [[NSOperation alloc]init];
NSOperation *op2 = [[NSOperation alloc]init];
[op1 addDependency: op2];
This way op1 won't start before op2 is finished.
You can create a method in your class where you call the download code and add a block as parameter which receives the downloaded UIImage, the image url (and other infos that you need) or you can implement a delegate with the same params from the block. It can lock something like:
-(void)downloadImageWithSuccess:(void (^)(UIImage *image, NSString *url, OtherParms here))success
failure:(void (^)(NSError *error)failure {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[arrImagem valueForKey:#"urlimagem"]]];
AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request imageProcessingBlock:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image){
Imagens *imagem = (Imagens *)[NSEntityDescription insertNewObjectForEntityForName:#"IMAGENS" inManagedObjectContext:managedObjectContext];
// Save Image
NSData *imageData = UIImageJPEGRepresentation(image, 90);
[imagem setCategoria:cat];
[imagem setTitulo:[arrImagem valueForKey:#"titulo"]];
[imagem setDescricao:[arrImagem valueForKey:#"descricao"]];
[imagem setImagem:imageData];
NSError *error;
if(![managedObjectContext save:&error]){
NSLog(#"houve um erro muito grave");
//return false;
}else{
NSLog(#"Salvou imagem");
}
success(imagem, [request.URL absoluteString], otherParams);
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){
NSLog(#"%#", [error localizedDescription]);
failure(error);
}];
[operation start];
}
}
And when you call the method from your code you can do something like(using blocks):
[catalog downloadImageWithSuccess:^(UIImage *image, NSString *url, OtherParms here) {
//NOTIFY USER THAT THE IMAGE WITH URL HAS BEEN DOWNLOADED
}
failure:^(NSError *error) {
//NTOFIY USER THAT THE IMAGE FAILED
}
];
managed to solve my problem, sorry for the delay in posting the solution, follow the code below:
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:strUrl]];
AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request imageProcessingBlock:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image){
//your implementation
dispatch_group_leave(group); //<== NOTICE THIS
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){
//your implementation
NSLog(#"%#", [error localizedDescription]);
}];
[operation start];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
Thus the downloads ocorerão in order, if this code is inside a case, the next download will only be called when the method success^: or failure^: is called
When the operation is running, I can not enter data in JSON model CREATED BY ACCELERATOR.
Can you tell me what I am doing wrong?
{
[super viewDidLoad];
NSLog(#"you are in a tableViewController");
self.title = #"NavigationOrdini";
NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.stampa6x3.com/json.php?azione=ordini"]];
AFJSONRequestOperation* operation;
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:req
success:^(NSURLRequest *request, NSURLResponse *response, id JSON)
{
[[ordiniModel alloc] initWithDictionary:JSON];
}
failure:^(NSURLRequest *request, NSURLResponse *response, NSError
*error, id JSON) {
[self setTitle:#"Dictionary"];
NSLog(#"failed! %d",[error code]);
}];
[operation start];
ordiniModel*test;
NSLog(#"il valore è %#",test.ordini.description);
}
AFJSONRequestOperation is asynchronous, meaning it that the code continues to execute while the rest of the app runs. The completion block are run when the code actually completes.
So try:
NSLog(#"you are in a tableViewController");
self.title = #"NavigationOrdini";
ordiniModel *test; // <-- create variable here
NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.stampa6x3.com/json.php?azione=ordini"]];
AFJSONRequestOperation* operation;
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:req
success:^(NSURLRequest *request, NSURLResponse *response, id JSON)
{
test = [[ordiniModel alloc] initWithDictionary:JSON]; // <-- Assign here
NSLog(#"il valore è %#",test.ordini.description);
}
failure:^(NSURLRequest *request, NSURLResponse *response, NSError
*error, id JSON) {
[self setTitle:#"Dictionary"];
NSLog(#"failed! %d",[error code]);
}];
[operation start];
I have found a way to queue JSON parsing operation to wait complete data parse, and this is the code:
- (void)LoadParse { // this method is called by a UIButton
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5.0];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// PARSING SUCCESS CODE
NSLog(#"operation completed"); <--- END OPERATION
[self anotherMethod]; <--- CALL METHOD AFTER OPERATION IS FINISHED
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON {
// PARSING FAILURE CODE
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation]; <--- START OPERATION
// I NEED TO SHOW A SORT OF INDICATOR TO ADVERT USER THAT OPERATION ARE STILL LOADING
// EXAMPLE: [DejalBezelActivityView activityViewForView:self.view withLabel:#"LOADING..."].showNetworkActivityIndicator = YES;
[queue waitUntilAllOperationsAreFinished];
}
The queue works perfectly: app waits the end of parsing operation, then it calls anotherMethod. But I need to show a sort of activityView to advert user when there is still loading operation: as u can see I've tried to add it between addOperation and waitUntilAllOperationsAreFinished but I cant see anything. IS IT THE RIGHT WAY? So, where is the RIGHT place to put activityView code to view it Until All Operations Are Finished, or another way to do that trick? Thanks!
Can use this code
- (void)LoadParse { // this method is called by a UIButton
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5.0];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// PARSING SUCCESS CODE
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON {
// PARSING FAILURE CODE
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
UIActivityIndicatorView *tempSpinner = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[self.view addSubview:tempSpinner];
[tempSpinner startAnimating];
[queue waitUntilAllOperationsAreFinished];
[tempSpinner stopAnimating];
//release tempSpinner if not using arc using [tempSpinner release];
[self anotherMethod];
}