How to show ProgressBar With AFNetworking AFHTTPRequestOperationManager - ios

I am trying to show the Progress Bar as I download a JSON from a url. The JSON is downloading correctly but I am not sure how to show the Progress Bar. I have tried using UIProgressView but it does not display on the screen. Any suggestions would be appreciated.
CGFloat width = [UIScreen mainScreen].bounds.size.width;
CGFloat height = [UIScreen mainScreen].bounds.size.height;
CGRect rect = CGRectMake(width/2, height/2, width/5, height/5);
UIProgressView *myProgressView = [[UIProgressView alloc]initWithFrame:rect];
myProgressView.progressViewStyle = UIProgressViewStyleBar;
[self.view addSubview:myProgressView];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:#"https:urlWithJson" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead)
{
myProgressView.progress = (float)totalBytesRead / totalBytesExpectedToRead;
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"operation Completed");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"ERROR");
}];
[operation start];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"timeout Error: %#", error);
}];

You set the download-progress-block inside the success block, which is a bit too late ;)
Try this:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFHTTPRequestOperation *operation = [manager GET:#"https:urlWithJson" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Complete");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
myProgressView.progress = (float)totalBytesRead / totalBytesExpectedToRead;
}];

Simple solution for Swift:
let progress: UIProgressView? //for example, reference to IBOutlet
let manager = AFHTTPRequestOperationManager()
let operation = manager.POST(query, parameters: parameters, constructingBodyWithBlock: { multipartData in
//do sth with your multipartData
}, success: { operation, response in
//success
}) { operation, error in
//failure
}
progress?.setProgressWithUploadProgressOfOperation(operation!, animated: true)
You do nothing more. This is enough to show progress on your view.

Related

iOS Block issue with AFNetworking

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

AFnetworking Cancel Specific Upload process

I m uploading multiple image my images on server, URL is same for all.
Following is the code.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy.allowInvalidCertificates = YES;
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSDictionary *parameters = #{KEY: VALUE};
NSString *imageUrl=[NSString stringWithFormat:#"%#/user/upload/item",BASE_SERVER_ADDRESS];
AFHTTPRequestOperation *op = [manager POST:imageUrl parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
NSString *imageName = [NSString stringWithFormat:#"IMG00%i.png",count];
[formData appendPartWithFileData:_imageData name:#"files" fileName:imageName mimeType:#"image/png"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %# ***** %#", operation.responseString, responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];
[op setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
double percentDone = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
//Upload Progress bar here
NSLog(#"progress updated(percentDone) : %f", percentDone);
}];
[op start];
I upload 10 images parallel and get the progress of each image individual. Now I want to cancel the specific uploading image, like 5th image.
How can I get the Operation of that image.
operationQueue has only NSOperation inside it. How will I know that specific NSOperation is the one I want to cancel.
Thanks.
You need to store operation you need to cancel in a variable, and later call [op cancel].

UIProgressView+AFNetworking not updating progress

I am trying to use the category UIProgressView+AFNetworking from AFNetworking UIKit.
I have an operation that uploads photos to a server. Mulitple photos at once. But my progress view isn't updating at all.
In my UIProgressView I use
[progressView setProgressWithUploadProgressOfOperation:operation animated:YES];
And my request is:
AFHTTPRequestOperation *operation =
[manager POST:url parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData name:#"imageFile" fileName:fileName mimeType:[NSString stringWithFormat:#"image/%#",fileMime]];
NSLog(#"Uploading...");
[SVProgressHUD showWithStatus:#"Uploading File..."];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
//Success
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//Fail
[manager.operationQueue cancelAllOperations];
}];
Try this:
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead){
double progress = (double)totalBytesRead / totalBytesExpectedToRead;
NSLog(#"Progress: %.2f", progress);
// ...
}];
I have my own progress bar, so I change its value in the setDownloadProgressBlock block.

AFNetworking 2.0 HTTP POST Progress

How can I get the progress of an AFHTTPRequest? I've tried searching all over the net.
I am using:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = #{#"gameId" : datas[0], #"p1": datas[1], #"p2":datas[2], #"turn":datas[3] };
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:#"http://localhost/thepath/isprivate/thefile.php"
parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
Is there like, a property or method I can use to access the progress of an AFNetworking 2.0 HTTP POST?
Try this:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = #{#"gameId" : datas[0], #"p1": datas[1], #"p2":datas[2], #"turn":datas[3] };
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:#"POST" URLString:#"http://localhost/thepath/isprivate/thefile.php" parameters:params error:&error];
AFHTTPRequestOperation *requestOperation = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"operation success: %#\n %#", operation, responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[requestOperation setUploadProgressBlock:^(NSUInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) {
double percentDone = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
NSLog(#"progress updated(percentDone) : %f", percentDone);
}];
[requestOperation start];
Hope this helps.
The shortest way way to implement this is
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFHTTPRequestOperation *requestOperation = [manager POST:#"/service/user/authenticate" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
//Your Business Operation.
NSLog(#"operation success: %#\n %#", operation, responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
//Here is the upload progress
[requestOperation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
double percentDone = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
//Upload Progress bar here
NSLog(#"progress updated(percentDone) : %f", percentDone);
}];
You can use following method
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
fromData:(NSData *)bodyData
progress:(NSProgress * __autoreleasing *)progress
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
of AFHTTPSessionManager class.
UPDATE:
Usually you will prefer to use KVO to get uploading values. So something like following should be used:
static void * kDGProgressChanged = &kDGProgressChanged;
...
[progress addObserver:self
forKeyPath:#"fractionCompleted"
options:NSKeyValueObservingOptionNew
context:kDGProgressChanged];
...
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(__unused NSDictionary *)change
context:(void *)context
{
if (kDGProgressChanged == context) {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateProgressInfo];
});
}
}

AFNetworking AFHTTPRequestOperation block is never called

I'm using AFNetworking to send a multipart form to a web-server, and i'm having some trouble with my AFHTTPRequestOperation. It's success and failure blocks are never called, after i start it.
Here is my code (a resume of it)
NSMutableURLRequest *request = [[ServerAPI sharedClient] multipartFormRequestWithMethod:#"POST" path:postUrl parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData> formData) {
[formData appendPartWithFileData:picture.picture_data name:#"InputFile" fileName:picture.name mimeType:#"image/jpg"];
}];
AFHTTPRequestOperation *operation = [[ServerAPI sharedClient] HTTPRequestOperationWithRequest: request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success");
} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure");
}];
[operation setUploadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
NSLog(#"%f", (totalBytesRead / (float) totalBytesExpectedToRead));
}];
[[ServerAPI sharedClient] enqueueHTTPRequestOperation:operation];
I can see the logs of the progress, but success and failure blocks are never called.
picture.picture_data is a NSData initialized with a UIImageJPEGRepresentation(image, 0.7)
ServerAPI is a subclass of AFHTTPClient, and sharedCliend is a singleton method.
Which are the reasons for AFNetworking don't call my blocks, not even with an proper error message?
Thank you all!
Edit
I do a get request with the same URL just before this one, and it works as usual. The URL i'm using is: part/_layouts/UploadEx.aspx?List=%7BD432BF97-7175-40C1-8E0D-27D8661CBC90%7D&RootFolder=%2Fpwa%2Fpart%2FLibrary&Source=http%3A%2F%2Fwww%2Emysite%2Ecom%2Fpwa%2Fpart%2FLibrary%2FForms%2FAllItems%2Easpx&IsDlg=1
In your code, check your postUrl . The BaseURL+postURL must be valid. Try upload image using normal web browser using URL BaseURL+postURL.
Edit
method HTTPRequestOperationWithRequest:success:failure: does not work for file uploading, but works for json/html fetching.
Try use
AFHTTPRequestOperation *operation = [[AFJSONRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
NSLog(#"%f", (totalBytesRead / (float) totalBytesExpectedToRead));
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure");
}];
[[ServerAPI sharedClient] enqueueHTTPRequestOperation:operation];

Resources