I'm impementing an application in iOS7, it's kind of a social network app with posts with images and a backend that saves all of the data sent form the client. The iOS client is sending the information of the post via json and after the info is sent, it starts to send the image via multipart form using AFNetworking
.
I need to be notified when the image is sent, so that I can refresh the main view of the app with the new posts, including the recently posted by the client. In the practice if I request the backend for the last posts and the multipart hasn't finished, the sending of the image gets interruped and fails to send the image.
The backend is develop in WCF
and is a RESTful JSON web service.
Here is the method that sends the post to the backend:
+(void)addPostToServerAddtext:(NSString *)text addimage:(UIImage *)image addbeach:(NSString *)beach location:(NSString*)location;
{
NSLog(@"entro a addPost");
NSString *urlBackend = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"URLBackend"];
NSData* dataImage = UIImageJPEGRepresentation(image, 1.0);
NSString* ImageName = [NSString stringWithFormat:@"%@_%@.jpg",idUser ,dateToServer];
NSString *jsonRequest = [NSString stringWithFormat:@"{\"Date\":\"%@\"...."];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@newPost",urlBackend]];
NSMutableURLRequest *request = [ [NSMutableURLRequest alloc] initWithURL:url];
NSData *requestData = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:requestData];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
if (image != nil) {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:[NSString stringWithFormat:@"%@FileUpload",urlBackend]
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:dataImage name:@"image" fileName:ImageName mimeType:@"image/jpg" ];
}
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success: %@", responseObject);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
}
}
A couple of thoughts:
You say:
Technically, you're not waiting for the information to be sent, but you're doing these concurrently. Do you want these to be concurrent? Or sequential? Or why not just a single request that posts the information as well as the image?
I'd suggest using AFNetworking for both requests. You've got a powerful framework for managing network requests, and it feels awkward to see hairy
NSURLConnection
code in there.If you keep the
NSURLConnection
code in there, note that you do not want tostart
aNSURLConnection
, unless you usedinitWithRequest:delegate:startImmediately:
withNO
for that last parameter. You're effectively starting it twice, which can cause problems. I'd suggest removing thestart
call.Setting all of that aside, what you want to do is to add a completion block parameter to your method, e.g., something like:
You'd then invoke that like so:
Now, I don't know what parameters you want to return in your completion block (I'm assuming you wanted to return what the
AFHTTPRequestOperationManager
did), but just change the parameters for thatcompletion
block as suits your needs.Unrelated to your original question, but I notice that you're building
jsonRequest
like so:That's a little risky if any of those fields include user supplied information (e.g. what if the user used double quotes in the information provided). I'd suggest you build a dictionary, and then build the
jsonRequest
from that. It will be more robust. Thus:Or, if you use AFNetworking, I believe it will do this JSON conversion of your dictionary for you. But, bottom line, be very wary about creating JSON strings yourself, at least if the request might include any user supplied information.