I'm just starting to get used to objective-c, before that I wrote a Java application for Android. Now I want to do the same application under ios.

In Android, I had a separate class that was responsible for server requests. In this class there was one internal method that sent requests to the server and received responses. And the request body was created in other methods that were already called from other parts of the program.

Further, in the right place of the program where I initialized this class, I created an asynchronous task, so that the UI would not hang then (because working with the network). And from this thread I already called the method I needed.

In obj-c, I figured out how to make requests to the server. I as a test in ViewController scored on pressing the button the execution of the code in which a request is made to the server.

NSString *login=[_loginFLD.text stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; NSString *password=[_passwordFLD2.text stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://freescribbler.com/test.php"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0]; request.HTTPMethod = @"POST"; //NSString* params = (@"act=LOGIN&username=%@&userpassword=%@&clientcode=123123123"); NSString* params=[NSString stringWithFormat:@"act=LOGIN&username=%@&userpassword=%@&clientcode=123123123",login,password] request.HTTPBody = [params dataUsingEncoding:NSUTF8StringEncoding]; NSURLSession *session = [NSURLSession sharedSession]; NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"response %@",dataString); }]; [dataTask resume]; 

Those. the point is that by clicking on the button, the data from the text fields (username and password) are retrieved and a POST request to the server is created. The answer comes and displayed in the log. There was no particular problem.

However, I want to bring this all to a separate class. Actually, there seems to be no problem. I created a separate class, created a method for it, where I inserted this code. Unless for experiment manually variables of login and the password hammered. I called this method when I pressed the button and everything worked just as well without any problems.

But I need this method to return a server response. This is what this method looks like. I tried to insert return after log output, but xCode swears. How do I get the method to return a server response?

 -(NSString*)loginTest{ NSString *login=@"***"; NSString *password=@"***"; NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://freescribbler.com/test.php"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0]; request.HTTPMethod = @"POST"; //NSString* params = (@"act=LOGIN&username=%@&userpassword=%@&clientcode=123123123"); NSString* params=[NSString stringWithFormat:@"act=LOGIN&username=%@&userpassword=%@&clientcode=123123123",login,password]; request.HTTPBody = [params dataUsingEncoding:NSUTF8StringEncoding]; NSURLSession *session = [NSURLSession sharedSession]; NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"response %@",dataString); }]; [dataTask resume]; } 
  • you cannot start an asynchronous task and execute a return after it has been executed - this is asynchronous, that the method ran long ago and the control flow went further. You need to either pass another completionHandler with the loginTest, which will be executed after NSLog, or create a protocol and pass the data to the delegate. Well, either as a less correct option, do NSNotification. - Max Mikheyenko
  • Thanks for the answer. But unfortunately, starting from the second sentence I did not understand anything - cheerful_weasel

1 answer 1

To return a value from a method with asynchronous requests, you must use a block.

On the example of your code:

 - (void)loginTestWithCompletion:(void(^)(NSString *string))completion { NSString *login=@"***"; NSString *password=@"***"; NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://freescribbler.com/test.php"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0]; request.HTTPMethod = @"POST"; //NSString* params = (@"act=LOGIN&username=%@&userpassword=%@&clientcode=123123123"); NSString* params=[NSString stringWithFormat:@"act=LOGIN&username=%@&userpassword=%@&clientcode=123123123",login,password]; request.HTTPBody = [params dataUsingEncoding:NSUTF8StringEncoding]; NSURLSession *session = [NSURLSession sharedSession]; NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"response %@",dataString); if (completion) completion(dataString); }]; [dataTask resume]; } 

PS Look at the AFNetworking framework, which makes working with the server much easier and the code more compact. In fact, it has already become the standard.

  • Thank. In general, the problem has already disappeared, I switched to swift and found a way out. - cheerful_weasel