I'm trying to write a method that will operate like this:
NSString *responseData = [myAwesomeWrapper getStringfromURL:#"http://spam.com"];
Behind the scenes, I want to do the request asynchronously (because I need authentication and HTTPS). The problem is obviously that asynchronous requests require delegate callbacks using didReceiveResponse. That prevents me from writing the tidy method I have in mind.
While I understand this approach, I'm sick of the complicating factor it's creating when I need to make several different requests and access the data directly from the same controller. Inventing ways to capture the data without conflicting with existing calls is growing old.
I've read about possibly using NSNotificationCenter to imitate this, but the examples I've read don't reveal an obvious way to make this work.
Is my C# brain asking for too much?
Full disclosure: I'm really new at Objective-C/Cocoa-Touch. Go easy on me. :)
Sounds like a job for ASIHTTPRequest
Related
I'm trying to do multiple request in background to download many jsons and check data from them but I don't know how to use AFNetworking in that case.
I tried to do like Wiki explaings but when it's going to download the second file then the app breaks. I want to do all the process in background.
Thanks
AFNetworking will definitely handle this. We use it for exchanging data with a RESTful set of services. The things to keep in mind:
An operation (eg. AFHTTPRequestOperation) can only be used once.
An operation is asynchronous.
Put your operations in an NSOperationQueue, or use AFHTTPClient (suggested) to manage the operations for you.
When sending multiple requests, always assume that the responses will come back in a random sequence. There is no guarantee that you will get the responses in the same sequence as the requests.
Hope this helps to point you towards a solution to your problem. Without more detail in your question, it's difficult to give you a specific answer.
Check out AFHTTPClient's
enqueueBatchOfHTTPRequestOperations:progressBlock:completionBlock:, which lets you enqueue multiple requests operations at once with the added bonus of having a completion handler that is called when all of those requests have finished, as well as a block for tracking the progress. Also note, that every single operation can still have its own completion handler (useful if you have to process the results of a request, for example).
If you don't need to customize the request operation (and don't need individual completion blocks), you can also use enqueueBatchOfHTTPRequestOperationsWithRequests:progressBlock:completionBlock:, which allows you to pass an array of NSURLRequest directly without having to build the operations yourself.
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 am just testing an app to get data off our web server, previously I had been using:
NSURL, NSURLRequest, NSURLConnection etc. to get the data that I wanted.
But I have just noticed that if I swap to using XML I can simply do the following and pass the results to NSXMLParser:
NSURL *url = [NSURL URLWithString:#"https://www.fuzzygoat.com/turbine?nbytes=1&fmt=xml"];
Am I right in thinking that if your just after XML this is an acceptable method? It just seems strongly short compared to what I was doing before?
gary
That code only creates a URL object that represents a URL. It doesn't make any request or download any data. You still need to use NSURLRequest and NSURLConnection in order to actually download any data from the server.
Also, stay away from methods like 'initWithContentsOfURL:` and friends, unless you understand that they will block the thread that they are called on until complete. For network services, this method shouldn't be used because it'll block your UI for an indeterminate time, because you can't predict how fast the internet connection will be wherever the app is used.
NSURLConnection's asynchronous request system is exactly what you need. It won't block the UI, and provides a nice encapsulated interface to downloading data from a remote location.
This is definitely the right way to go. There do exist many different connection methods (including my favorite, ASIHTTPRequest) and many, many different xml parsers (including my favorite, KissXML) that are faster or more memory efficient than the Apple built in methods.
But to answer your question, yes, your logic and design pattern is correct.
UPDATE: Because Jasarien seems to think the question talks about asynchronous actions, I will discuss that here. ASIHTTPRequest handles async very very easily. Just check out the quick samples.
Depending on how much XML you get back from the web service, NSXMLParser may not be ideal because the entire XML document has to be read into memory.
Memory is pretty scarce on an iPhone, so using a SAX parser like that in libxml2 is probably better for larger XML files. Instead of reading the entire document into memory, the XML is streamed through and parsed for specific nodes of interest. The memory overhead is lower because less data is stored at once.
Once a node of interest is parsed, an event handler is called to do something useful, like store the node data somewhere.
In this case, take a look at Apple's XMLPerformance sample project for example code.