Not even sure if the title is correct, however, what I'm trying to do is use the standard NSURLConnection class to handle responses from calling my webservice. I am using the POST method to update a database and the GET method to retrieve rows from the database. The problem I have is that these 2 actions may occur simultaneously so that the methods to handle the request may step on each other. In other words in my "connection didReceiveData" method I have 2 paths through the code depending on whether I'm handling a response from a GET or POST request.
I keep track on which request in being processed by an instance variable called requestType. The problem is that since the requests are being executed simultaneously the instance variable is being changed from GET to POST before the GET completes (or vice-versa). My question is how do I maintain 2 separate requests in this scenario? Do I synchronize the requests? Is there a way for threads to work here? Do I create 2 separate objects for each of the requests and have the logic in "didRecieveData" query for which object is being processed? Any help would be much appreciated!!
Dealt with a similar issue in one of our apps. The solution involved creating a class that represents a webservice call, responsible for calling its own url, loading its own data, etc. The call class had a delegate that would handle parsing the responses (in our case, a web service controller). Wound up getting rather complicated, but prevented the issue of NSURLConnections stepping on each other.
Seems like you've created a messy problem by having a class that tries to do too many things. I would suggest taking one of the following three approaches:
1) Write two classes, one for updates and one for retrievals. Each class creates it's own private NSURLConnection object and acts as the delegate for the async notifications received from the NSURLConnection. The classes could possible share some utility parsing code or extend a base object that has that parsing code in it. But the key being that the code calling these classes would instantiate one of them, make the call, and then release it. This will keep your code cleaner and will insure that the event notifications don't get intermingled.
2) Create a single class that, depending on initialization, does either a post or a get with it's own private instance of NSURLConnection. When a call needs to be made, instantiate the class, get the results, and then release the class.
3) Write your connection handling classes so they use the synchronous NSURLConnection method and call that call that class in a background thread.
Either way, clean code and clear object orientation will prevent messy scenarios like the one you're describing.
Create separate objects that handle the calls. If you want to issue multiple requests at once I would strongly recommend looking at NSOperationQueue, and making these objects subclasses of NSOperation... much nicer way to deal with multiple background requests.
A good example is here:
http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/
The idea there is that you use the non-asyncronous web calls, in operations that are run on separate threads. You can still use asynch calls in NSOperation as well, but doing so is a little trickier and for simple calls you probably do not need to.
Related
I need to send a server a set of requests with some data. The data in the subsequent requests will be determined based on the server response in the earlier requests. I do not want to use synchronous approach with NSURLConnection class, as it is very limiting (for one of the requests, for instance, i need to prevent redirects. According to Apple Dev documentation this can only be done with Delegate implementation).
Depending on which request in the chain it is, i need to be doing different things (send different messages to various classes).
The way i see it now, is that i have to either create n delegates for each of my requests, or create a delegate which would initWithFlag and then create the instances of that delegate with different flags, or i need to use something like a factory pattern which would be pretty similar solution to the second one.
I do not WANT to implement a delegate at all, i want to send requests with the least bit of coding possible.
I am also not looking at any frameworks (ASIHTTPRequest etc), i would like to do it with the native classes.
What would be the best approach?
I know you said you don't want to use third party frameworks, but I'd really suggest AFNetworking. With that said, you do not NEED AFNetworking or any third party library, it will just make your life easier IMHO.
So, what I have done in a similar scenario is essentially use the Command Pattern. When I want to send off one of these complicated "requests" I initialize a command object, set all of the necessary parameters and then call execute. My command object has completion and failure handlers/blocks and execute is an asynchronous call.
Within the command I have different 'steps' that are effectively synchronous and depend on each other. Let's say request A depends on B and B depends on C, the first step of the command is to execute A on it's own queue (I am using GCD with a private queue) and wait for it to finish. Once A finishes (successfully) I continue on to B and pass in any results I need from A into B. Likewise for B->C. If any of the intermediate requests fail throughout the process I can execute the failure block and handle it from where I executed the command (consumer end). If all finish successfully I execute the success block.
I prefer the encapsulation of this approach as it is very easy to re-use throughout the project, all of the intricacies are tucked away in the command's implementation.
Oh and the fact that I use callbacks/blocks I did not need to implement any delegates. In your case using the NSURL classes your command object would be the delegate of any of those instances.
I have settled on implementing the delegate after all.
The key things that tripped me were:
Do NOT declare the delegate methods in .h file. They won't work like that. Simply add them to implementation.
A delegate can be init'ed within the NSURLConnection initWithRequest method or it can be held as a property of the parent class, there is no difference.
The best way to handle multiple requests is the suggested initWithFlag. Therefore, it is best to create a delegate when initialising connection. The delegate lives long enough to perform full data transfer under ARC.
The most convenient way to cancel the redirect comes from Apple's Developer Library:
-(NSURLRequest *)connection:(NSURLConnection *)connection
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)redirectResponse
{
NSURLRequest *newRequest = request;
if (redirectResponse)
{
newRequest = nil;
}
return newRequest;
}
Please note that this message is sent several times during the life of the connection for undisclosed reasons. However, if the response is not an actual redirect, the redirectResponse will be nil.
Setting the request to nil will cancel the redirect, but NSURLConnection will finish processing the original data (that is, connectionDidFinishLoading message will be sent).
You can cancel this behaviour by sending this message:
[connection cancel];
I found NSNotifications to be the best way to pass results to the parent class.
I'm working on a new iPhone/iPod app that includes the need to do web services requests. I've found methods for doing these requests synchronously, or asynchronously by setting the controller as the delegate. What I'd really like to be able to do, though, is to create a single class that can handle all web requests for the whole application, and just create an instance of that class when I need to use it. That way, cookies and common pieces of code can be handled in one place, rather than all over the app.
So far the only thing I thought of that could accomplish what I'm trying to do is to create a new thread that handles the request synchronously within itself, then sends a message back to the calling controller once the request is complete. Is there a better way to accomplish what I'm trying to do?
Cookies are already a shared resource.
I would suggest reading the URL Loading System Overview to get an idea of how Apple set everything up. From what you describe, you want something very similar to how they have set up the system, maybe with a Singleton class for the connection. You can also look at ASIHTTPRequests which is a good wrapper around all of the connections stuff.
I would not suggest writing my own code here. Lots and lots of people have solved this problem for you.
I have a few apps that I am trying to develop a reusable URL connection layer. I have done some research and am struggling between architectures. Specifically the APIs this layer utilizes.
In the past, I have used NSURLConnection and NSOperation on a separate RunLoop. This seems overkill. I've seen libraries that subclass NSURLConnection. Others have a singleton Engine object that manages all requests.
The Engine and/or NSURLConnection seem best to me. But I am asking for input before I go too far down one road. My goals would be:
Ability to cancel a request
Concurrent requests
Non-blocking
Data object of current open requests
Any direction or existing references with code samples would be greatly appreciated.
I'm not sure about a "data object of current open requests", but ASIHTTPRequest does the first three and is very easy to use.
Update
Actually, it looks like ASINetworkQueue may fulfill your last bullet point.
I personally use a singleton engine with my large Apps though it might not always be the best case. All the URL's I use require signing in first, figured it would be best if one Class handles all of the requests to prevent multiple URLS from signing into the one location.
I basically create a protocol for all my different connection classes into my singleton and pass the delegate of both the calling class and the singleton into it. If an error occurs its passed to the singleton so it can deal with it, if it completes it returns the data to the calling class.
Im using a large amount of very small web services in my app and I have been down a couple of roads that does not scale or work as desired.
The Design approach Im thinking about:
The task for the viewController is to ask for a set of data from a general webServicesClass, this task is started in a new NSThread -> this will instantiate an object which solely retrieves the xml and returns it to the webServicesClass -> the webServicesClass now instantiates an object which solely can Parse some XML coming from this particular web service. The Parser then returns a nice Entity object to the webServiceClass. The WebserviceClass now needs to inform the viewController about this data.
The viewController implements a webServiceClassDelegate and some delegate methods to see if the web service request went as planned. e.g. -(void)aWebserviceFailed and -(void)aWebserviceSuccess.
0.5 Since the WebserviceClass is running is a different NSThread, will it be a problem calling delegate methods on the main NSThread in the parent object?
1.0 I think this design is sound as it completely incapsulates the retrieval, parsing and returning of the Entity in different classes. But, I will have to write delegation methods and implement delegation protocols on each step of the way, for each different webservice. i.e. starting from the bottom, the WebserviceClass must implement delegation methods for both the object that retrieves the XML (start, fail, success), then for the object that parses the XML(start, fail, success) and the WebserviceClass must be able to delegate each of these responses to the viewController that again must implement delegation methods from the WebserviceClass(start, fail, success).
Is there a much simpler way to do this?
I have some design pattern experience, but not from languages that uses delegation so consistently as Objective C. In AS3 or Java I would have events that could bubble up through the objects and inform whoever was listening about changes. In all the Objective example code I have read I have only seen NSNotifications (which would be the equivalent of the AS3 or Java 'Event') used 0.1% of the times.
The Design I described will give me something that scales perfectly for many web services and gives me complete control over where a potential error/exception happens, but it seems to be a lot of code to obtain this loose coupling.
1.1 Or should I fully embrace the delegation approach and get to work:)
Thanks for any pointers or help given. Im not asking for source code or the likes, more a "this is considered best practice in Objective C in the every day situation you just described" :)
I'd recommend taking a look at ASIHttpRequest(obtainable here) and NSOperation + NSOperationQueue (docs here). I don't think you should run a long-lived thread to talk to your web service all the time, unless you absolutely need a constant connection.
Basically ASIHttpRequest and NSOperation both encapsulate all of the networking and threading stuff. Operations make multi-threading on the iPhone really nice. Essentially you create an operation (through a factory or whatnot for ease of use), pop it in a queue and do something with the result.
As for what you do with the result (this applies to your original scenario too and 0.5 and 1.1) what typically happens is your operation/thread will then call a didSucceedAtGettingWhatever or didFailWithError:(NSError*) method. Delegation is pretty much the defacto way of making requests on the phone. If there are multiple delegates, then you can just use subject-observer, like you would in Java.
As for 1.0, ultimately no. What we typically do is we have an OperationDelegate and OperationTypes. Based upon which OperationType succeeded or completed, we have different logic. It's not the greatest and there are a ton of different ways of doing this, but you will have to have separate logic for separate events regardless of what you do. Whether or not that's in one method or many methods is up to you.
I have an app that makes SOAP calls. To keep the UI from blocking, we are putting each SOAP call into a subclass of NSOperation. This works well, but we have a ton of different types of SOAP calls. So if we use 3 WSDLs each with 10 Ports or Operations, then we 30 different calls in SOAP and if we put each of those in a thread using NSOperation, we end up with 30 NSOperation subclasses.
This may not be a bad thing, but we are trying to create a reusable library, so we have one object per WSDL which encapsulates the calls. This is nice because we are using WSDL2ObjC and this encapsulates all that logic. But it seems odd then to have a nice api that we wrap calls to in these many NSOperations. Also, we are doing the threading in the api itself, so that the invoker can use it how he/she sees fit.
Any suggestions would be great.
If I'm understanding you correctly you already have objects that encapsulate the calls to the SOAP service and you just want to cut down on the NSOperation subclasses.
Have you checked into NSInvocationOperation? It's a subclass of NSOperation that let's you make a message send to an object as an NSOperation call. So you still getting the non blocking operation, but you don't need multiple subclasses of NSOperation.