Undoubtedly, people will shake their head in shame at the following, but I would appreciate the help.
I seem to make the same calls to NSURLSessionUploadTask with pretty much the same structure throughout the program. Hence, I am trying to make it a method which I can call from anywhere in the program and, when it's complete, return the NSDictionary to the call which made it.
Currently I have the following:
-(NSDictionary *)serverRequest:(NSString *)requestURL withDictionary:(NSDictionary *)sendDict {
NSURL *homeURL = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@/%@",baseURL, requestURL]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:homeURL];
[request setHTTPMethod:@"POST"];
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setCachePolicy:NSURLCacheStorageAllowedInMemoryOnly];
NSData *sentData = [NSJSONSerialization dataWithJSONObject:sendDict options:0 error:nil];
NSURLSessionUploadTask *uploadTask = [_session uploadTaskWithRequest:request fromData:sentData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
returnedData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
if ([returnedData[@"code"] isEqualToString:@"OK"])
{
dispatch_async(dispatch_get_main_queue(), ^{
return returnedData;
});
}
}];
[uploadTask resume];
}
So I pass in the URL I want to call, and the NSDictionary which is then sent to the server. The server replies, with a JSON response, which I then turn into returnedData. I simply wish to pass this data back to the call which made it ... something like:
NSDictionary *mydata = @{@"email": userRegisterTextFieldEmailAddress.text};
NSDictionary *passedBackData = [self serverRequest:@"checkUserName" withDictionary:mydata];
When I try this it won't build as the dispatch_async isn't the right format etc, etc. I have tried to read up on this, and can't believe it's a hard problem? Surely others aren't making the same call with the same code each time they want to return some data from a web server?
Thanks in advance for any help you can give in clearing up my misunderstanding.
What you'd generally do is add a completion block parameter to your method, that specifies what you want to do upon receiving the response. So, add a block parameter to your method and add the code that calls that block, something like:
- (void) serverRequest:(NSString *)requestURL withDictionary:(NSDictionary *)sendDict completion:(void (^)(id responseObject, NSError *error))completion
{
NSURL *homeURL = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@/%@", baseURL, requestURL]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:homeURL];
[request setHTTPMethod:@"POST"];
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setCachePolicy:NSURLCacheStorageAllowedInMemoryOnly];
NSData *sentData = [NSJSONSerialization dataWithJSONObject:sendDict options:0 error:nil];
NSURLSessionUploadTask *uploadTask = [_session uploadTaskWithRequest:request fromData:sentData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// report any network-related errors
if (!data) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(nil, error);
});
}
return;
}
// report any errors parsing the JSON
NSError *parseError = nil;
returnedData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
if (!returnedData) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(nil, parseError);
});
}
return;
}
// if everything is ok, then just return the JSON object
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(returnedData, nil);
});
}
}];
[uploadTask resume];
}
You'd then call this serverRequest method, specifying precisely what you want to do with the data you receive:
[self serverRequest:url withDictionary:dictionary completion:^(id responseObject, NSError *error) {
if (responseObject) {
// do what you want with the response object here
} else {
NSLog(@"%s: serverRequest error: %@", __FUNCTION__, error);
}
}];
Clearly, you can change this as you see fit, but hopefully this illustrates the idea. If, for example, you knew that responseObject was always going to be a NSDictionary, then I'd change the references to id responseObject with NSDictionary *responseObject.
But the idea is that you should just provide a block that takes the response data and/or the error as parameters. That way, the code that calls this method can specify what should happen when the asynchronous network request completes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With