AFNetworking 2.0 HTTP POST Progress - ios

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];
});
}
}

Related

Sending array of dictionary with afnetworking 2.0

I've a big problem, I'm trying to send an array of dictionary with afnetworking, that's my code:
checkDeliveryParams = #{#"cart_total":#(cart_total),#"shipping":#{#"address":[User sharedInstance].shipping_city,#"country":#"IT",#"postcode":[User sharedInstance].shipping_postcode,#"state":[User sharedInstance].shipping_provincia},#"user_id":#([User sharedInstance].user_id),#"cart_contents":temp};
cart total it's an array like this
(
quantity:1
product_id:2
)
but server receive something like this
(
quantity:1
),
(
product_id:2
)
my request code is
+(void)GET:(NSString *)path
params:(NSDictionary *)params
auth:(BOOL)authenticate
success:(void (^)(NSDictionary* responseObject))success
failure:(void (^)(NSError *error, NSDictionary* responseObject))failure{
NSString *URLString = [#"" stringByAppendingPathComponent:path];
NSLog(#"GET - API URL: %#", URLString);
AFHTTPRequestOperationManager *manager = [Rest commonManager:path sendAuthToken:authenticate];
// manager.requestSerializer=NSJSONSerialization ;
[manager GET:URLString parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary *responsedata){
NSLog(#"ok della richiesta %#",responsedata);
[Rest verbose:responsedata];
success(responsedata);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"errore della richiesta %#",error.localizedDescription);
failure(error,[Rest parseErrorResponseForOperation:operation]);
}];
}
I've tried a lot of method, I've tried to set nsjonserializer, "application/json", I've already tried to use NSURLSessionDataTask...
Sorry for my English, someone can help me ?
the common manager call in [rest commonManager] is defined in this method
+(AFHTTPRequestOperationManager *)commonManager:(NSString *)path sendAuthToken:(BOOL)sendToken{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
manager.securityPolicy.allowInvalidCertificates = NO;
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Accept"];
if([Session isOpen] && [Rest authorizationRequiredForPath:path] && sendToken){
[manager.requestSerializer setValue:[NSString stringWithFormat:#"Bearer %#", [Session token]] forHTTPHeaderField:#"Authorization"];
}
return manager;
}
that's how I send parameters in get call
+(void)GET:(NSString *)path
params:(NSDictionary *)params
auth:(BOOL)authenticate
success:(void (^)(NSDictionary* responseObject))success
failure:(void (^)(NSError *error, NSDictionary* responseObject))failure{
NSString *URLString = [#"" stringByAppendingPathComponent:path];
NSLog(#"GET - API URL: %#", URLString);
AFHTTPRequestOperationManager *manager = [Rest commonManager:path sendAuthToken:authenticate];
// manager.requestSerializer=NSJSONSerialization ;
[manager GET:URLString parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary *responsedata){
NSLog(#"ok della richiesta %#",responsedata);
[Rest verbose:responsedata];
success(responsedata);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"errore della richiesta %#",error.localizedDescription);
failure(error,[Rest parseErrorResponseForOperation:operation]);
}];
}

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].

Trying to make a function to handle AFNetworking

I'm trying to make a function that I'll call to handle the AFNetworking JSON parse.
Here is my code:
- (int)startParseWithParameters:(NSDictionary*)incomingParameters andUrlAdress:(NSString*)urlAdress;
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSDictionary *parameters = incomingParameters;
[manager POST:urlAdress parameters:parameters success:^
(AFHTTPRequestOperation *operation, id responseObject)
{
NSString *recivedErr = responseObject[#"error"];
_errValue = [recivedErr intValue];
NSLog(#"JSON: %d", _errValue);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#", error);
}];
return _errValue;
}
I want the function to return 0 or 1, then I'll know if there is an error or not.
Right now it always return 0.
When I try to return in the success block I get a compiler error.
What could cause this problem?
The succes block is handled async so you should just call a method in the block:
- (void)startParseWithParameters:(NSDictionary*)incomingParameters andUrlAdress:(NSString*)urlAdress {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSDictionary *parameters = incomingParameters;
__weak typeof(self) weakSelf = self;
[manager POST:urlAdress parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *recivedErr = responseObject[#"error"];
[weakSelf didReceiveResponse:[recivedErr integerValue];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
-(void)didReceiveResponse:(NSInteger)status {
}

AFNetworking 2.0 track file upload progress

I am relatively new to AFNetworking 2.0. Using the code snippet below, I've been able to successfully upload a photo to my url. I would like to track the incremental upload progress, but I cannot find an example of doing this with version 2.0. My application is iOS 7, so I've opted for AFHTTPSessionManager.
Can anyone offer an example of how to modify this snippet to track upload progress?
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:#"myimage.jpg"], 1.0);
[manager POST:#"http://myurl.com" parameters:dataToPost constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData name:#"attachment" fileName:#"myimage.jpg" mimeType:#"image/jpeg"];
} success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(#"Success %#", responseObject);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"Failure %#, %#", error, [task.response description]);
}];
The interface of AFHTTPSession doesn't provide a method to set a progress block. Instead, you'll have to do the following:
// 1. Create `AFHTTPRequestSerializer` which will create your request.
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
// 2. Create an `NSMutableURLRequest`.
NSMutableURLRequest *request =
[serializer multipartFormRequestWithMethod:#"POST" URLString:#"http://www.myurl.com"
parameters:dataToPost
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData
name:#"attachment"
fileName:#"myimage.jpg"
mimeType:#"image/jpeg"];
}];
// 3. Create and use `AFHTTPRequestOperationManager` to create an `AFHTTPRequestOperation` from the `NSMutableURLRequest` that we just created.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFHTTPRequestOperation *operation =
[manager HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure %#", error.description);
}];
// 4. Set the progress block of the operation.
[operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
long long totalBytesWritten,
long long totalBytesExpectedToWrite) {
NSLog(#"Wrote %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite);
}];
// 5. Begin!
[operation start];
In addition, you don't have to read the image via UIImage and then compress it again using JPEG to get an NSData. Just use +[NSData dataWithContentsOfFile:] to read the file directly from your bundle.
It's true the interface of AFHTTPSessionManager doesn't provide a method to track the upload progress. But the AFURLSessionManager does.
As a inherited class of AFURLSessionManager AFHTTPSessionManager can track upload progress like this:
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST" URLString:kUploadImageURL parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:UIImageJPEGRepresentation(image, 0.5) name:#"uploadFile" fileName:#"image" mimeType:#"image/jpeg"];
} error:nil];
NSProgress *progress;
NSURLSessionDataTask *uploadTask = [[AFHTTPSessionManager sharedManager] uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (!error) {
//handle upload success
} else {
//handle upload failure
}
}];
[uploadTask resume];
[progress addObserver:self forKeyPath:#"fractionCompleted" options:NSKeyValueObservingOptionNew context:NULL];
outside
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:#"fractionCompleted"] && [object isKindOfClass:[NSProgress class]]) {
NSProgress *progress = (NSProgress *)object;
//progress.fractionCompleted tells you the percent in CGFloat
}
}
Here is method 2(updated)
use KVO to track progress means self need to be alive during observation. The more elegant way is AFURLSessionManager's method setTaskDidSendBodyDataBlock, like this:
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager setTaskDidSendBodyDataBlock:^(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
//during the progress
}];
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST" URLString:kUploadImageURL parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:UIImageJPEGRepresentation(image, 0.5) name:#"uploadFile" fileName:#"image" mimeType:#"image/jpeg"];
} error:nil];
NSURLSessionDataTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (!error) {
//handle upload success
} else {
//handle upload failure
}
}];
[uploadTask resume];

Resources