views:

272

answers:

2

Ok, This may be a very simple question to ask with a very obvious answer but I'm a little stuck on the best way to solve this problem.

I am coding an objective-c application using the iPhone SDK. I have some custom objects. These objects execute an NSURL request and send data to a web server, retrieve data back and move on.

My problem is that I have an initial request going to the server where I am authenticating. This request if successful returns some information for a session that I will use in the following request. If I want my application on start up to authenticate and then make an initial subsequent request I need the data from the first to perform the second. My problem is that in objective-c when I send a message to the request object to execute the request and return data to a variable as a result; the language by nature continues executing my method while the first request is in process. My second request can never be successful due to the first one not having returned data yet.

I don't remember what this is called but It is something in the line of running procedural code, single threaded code versus parallel processing or something.

What is the best way to hold my method's execution until the object that is sending the web request gets it's return value?

I am sure there are a few ways of doing this but I'm looking for what would be considered 'proper'.

Example sudo code below.

//First Request is sent obtaining some data that we will soon manipulate  
MyClient *client = [[MyClient alloc] init];  
NSString *returnData = [MyClient runRequest];  

//Call an object that now plays with the data and does some neat things  
CustomObject *CustomObj = [[CustomObject alloc] init];  
[CustomObj dealWithResponse:returnData];   
//Problem is now when I process the return data, it hasn't completed the first request from line 2 yet  
+4  A: 

You're talking about "synchronous" vs "asynchronous" operations. Synchronous operations are ones that happen in step with your calling code. Most of Cocoa works this way: you send a message to an object, say to format a string, etc, and by the time that line of code is "done", the operation is complete.

But in the real world, some operations take longer than "instantaneous" (some intensive graphics work, but mainly high or variably latency things like disk I/O or worse, network connectivity). These operations are unpredictable, and if the code were to block until finish, it might block indefinitely or forever, and that's no good.

So the way we handle this is to set up "callbacks"-- you say "go off and do this operation, and when you're done, call this other function". Then inside that "callback" function, you start the second operation that depends on the first. In this way, you're not spinning in circles waiting, you just get called "asynchronously" when each task is done.

NSURLConnection (like other high-latency objects) lets you follow this pattern. You set up a delegate when you create the connection, and the delegate gets called on certain methods when resulting data is available. This way, you can serialize your operations by having the delegate method start the second operation only when the first is complete.

quixoto
Ben, You are absolutely right. Normally call back function would be the way to go here. I guess I need to think about the implementation a bit more here.Essentially what I am hoping for is a synchronous connection with a timeout of some sort. The end goal is to have a Client object of sorts that can make a web service call and if no response comes back within a short period of time it would trigger an error. If response comes back then UI actions occur and another request can be triggered. But while we are waiting for the data or the error I can't make any other calls. Queues maybe?
Hazmit
This answer is right, you should return immediately. The callback function later on that handles the response is then responsible for processing the data or displaying an error. this concept is called event driven programming. http://en.wikipedia.org/wiki/Event-driven_programming
Jacob
A: 

I spent some additional time looking through the NSURLConnection documentation and found an instance method that allows you to submit synchronous requests.

Ben's answers and commentary on programming concepts are perfectly correct and should be thought of as the true answer to the question. However, for those who really really want to submit a synchronous request and have your application's execution blocked until there is a response you can use the following method.

sendSynchronousRequest:returningResponse:error:  

This can be found in Apple's class documentation for NSURLConnection

http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html#//apple_ref/occ/clm/NSURLConnection/sendSynchronousRequest:returningResponse:error:

Hazmit