Been banging our heads on this for two weeks now. Any help will be greatly appreciated.
Problem:
I am using NSURLConnection to fetch JSON data from a RESTfull Web service, the requirement is such that I can't do lazy loading of data. It is one big chunk of data that needs to be processed on the 1st screen of the app every time the logged in user opens the app. I know its not a smart thing to do, but can't help it. The caching is being done in the local Sqlite DB. We are using Async NSURLConnection that is giving us a constant 3-4 sec hit on the performance.
We tried Sync NSURLConnection and figured out the Async NSURLConnection is taking around 3-4 sec extra to process the same request. But Sync NSURLConnection is not reliable at all, it fails to get the complete JSON more than half of the times. And the combination of Sync NSURLConnection with NSOperation will not help.
We tried making the call in a separate app just to observe the performance for that one particular request, and still got the same results.
So, currently we are getting an average execution time of the complete request to be around 6-8 sec. Which we feel I quite high for your first screen of the app. (please let me know if its not much, it feels like bad user experience to me).
Questions:
Isn't NSURLConnection the standard way for doing a request like this?
Is there a better and faster (reliable) way of doing this apart from NSURLConnection?
Can I optimize the performance of NSURLConnection? If yes, please point me to the right direction.
Has anyone tried CFHTTPStream? If yes, then is it better than NSURLConenction in terms of performance?
Thanks
#GoZoner Thanks a ton for the response. We tested in the below three ways
Since it is the 1st screen of the app, so there is no real case of the app doing anything else, still the results were different and a consistent 3-4 sec loss with Async.
We made a raw call in a separate test app, which did nothing but just that one web service call and still the results were same.
We tested on the device and on the simulator. On the device, as expected the results were worse, around 4 secs constant lag in an Async NSURLConnection call.
We were also surprised with the reliability issue as it makes very little sense that a Sync NSURLConnection is unreliable. But after running the tests a zillionth time we realized that it is actually not reliable, not because of something in the NSURLConnection library, but because the 3G or Wi-fi connections are not reliable so the call use to break mostly due to the connection(my assumption). This particular problem is handled beautifully by Async NSURLConnection since it keeps calling and appending data till the data received is complete.(This can sometimes take more than 10-12 attempts to append the data to complete the JSON). Since the Sync NSURLConenction is making only one attempt in getting the data, it fails miserably in the unreliable mobile network connectivity.
#Andrea Thanks for the response :) Will surely give YAJL a spin. But i believe that the problem is more with the connection rather than the parsing of the JSON, I may be wrong. Does YAJL have a reliable connection handling mechanism?
Looking forward to more responses, your suggestions and comments are actually very valuable :)
Thanks
try to use ASIHttpRequest the response time may be faster than the NSURLConnection.
Related
My app is calling a web service to retrieve some data, and I want to make the experience as best as possible. I figured out that using NSURLConnection it's very hard to give good timely feedback.
Sometimes my iPhone tries to load the data for a minute or two and I see no way of figuring out what is taking so long, or why the download is so troublesome. Then after a few minutes I sometimes end up with an error code.
I'd like to display exactly what is happening. Messages like:
"Establishing internet connection"
"Trying to connect to server"
"Connected..."
"Downloading data..."
"Download complete!"
And when there is trouble like server not reachable or DNS could not be resolved, it would be nice to just try again a few times and not simply quit and throw error.
Are there replacements for NSURLConnection which handle these things more gracefully and give better in-time feedback about what is happening?
I've been a big fan of the AFNetworking library. Very easy to use and wraps all your networking calls in blocks that are very easy to work with.
It is also is kept very current, so you should be safe in getting all the updates it needs as your project progresses and ages.
I think you should be misusing NSURLConnection and NSURLConnectionDelegate, since you can do most of you needs with them.
But, what about MKNetworkKit? I've been using it and it really makes those kind of issues easier to deal with.
Something that can help you achieve what you want. Since ASIHTTPRequest is no longer being supported MKNetworkKit would be your best choice. To check for connectivity, you can always use Reachability.
My app is able to consume a wcf using ASIHTTPRequest. But the thing is that i need to check the server hour every one minute. So i need a request to the server every one minute. What is more, sometime i will need to refresh the clock every one second.
the app is a items auction so i need to get the hour no matter what.
so my question is, is this going to kill the iphone?
ASIHTTPRequest have a method to achieve this? making calls every XX time?
some good way to do it?
Thx in advance!
Assuming the data you are getting back isn't larger than the memory threshold, and you are properly managing memory on your end, AND you are performing an asynchronous request (or a request on a background thread), this shouldn't kill the app memory-wise or cause it to hang.
I do something similar, where every 2 minutes I ping my server for updates. I achieve this using an NSURLConnection and NSURLRequest, though I imagine ASIHTTPRequest is not much different. I typically use a recurring timer that, when invoked, calls a method which, using Grand Central Dispatch, sets up my request/connection and fires.
I have an app that needs to upload a least 5 photos to a server using API call available with the server. For that I am planning to use threads which will take care of photo upload and the main process can go on with the navigation of views etc. What I cant decide is whether it is OK to spawn five separate threads in iphone or use a single thread that will do the upload. In the later cases obviously it will become quite slow.
Basically an HTTP POST request will be made to the server with the NSMutableURLRequest object using NSCOnnection.
More threads mean more complexity and sync issues, but I can try to write code as neat as possible if it means better performance than a single thread which is simple but is a real stopper if performance is considered.
Anybody with any experience in this kinda app. ??
I would suggest using one extra thread and queuing the uploads, one after the other. You'll end up clogging the network interfaces if you try 5 uploads concurrently. Remember that the iPhone will often be on a 3G or even EDGE connection, not always WiFi, so photo uploads can be really slow, and even slower if there are 5 at once.
You could probably benefit from using NSOperation and NSOperationQueue to nicely handle the ugly threading for you. Wrap up an upload process into an NSOperation, and then queue 5 of them for each image. Should work quite nicely.
Jasarien thanks for the bit on NSOperation and NSOperationQueue. It did simplyify in great measure. But right now I hve run into a major issue.
I spawn an extra thread from the main thread. This thread queues up each of the picture upload operation. So this thread queues up 5 picture opload operations in a queue. This is absolutely fine when working with Mac PC. Now when I push the app to the device, only one pic upload is successful and the rest fails. Most of the cases of failure are due to server time out error. So basically I am wondering, whether NSOperationQueue ensure only one operation at a time or not ? I mean if the first pic upload is in progress and say the next operation is already added in the queue. Would it create an extra thread for the second operation too while the first one is running ? I think as the name suggests, it must wait in the queue until the previous one is done. Not sure how to go abt doing it. I am uploading pic which are taken with iphone camera.
I went to the iPhone Developer Tech Talk a few months ago and asked one of the gurus there about the lack of NSHost on the iPhone. Some code I was porting to the iPhone made significant use of NSHost throughout its networking code.
I was told that NSHost is on the iPhone, but its private. I was also told that NSHost is a synchronous API and that I shouldn't use it anyway. (If anyone could elaborate on why it shouldn't be used, as a bonus, that'd be great.)
I can see the caveats of using synchronous API's on the main thread in that they'll block until complete - and that's never a good thing with network code because there are so many factors that could cause the API to block the thread for a significant amount of time.
My solution was to write a wrapper around CFHost's asynchronous resolution functions.
The result works quite well, and I'm considering releasing it into the public domain.
But my question is this: Say my app only resolves a hostname once per run, during the connecting phase, and then cache's it for the rest of the session. During the time it is resolving, a modal screen is shown telling the user "Connecting" with a nice spinner.
Does it really matter whether or not the resolution is asynchronous?? The user has to wait to connect anyway, and the resolution is only done on the first connection. Subsequent connections use the cached result of the resolution.
When is it OK to be synchronous and when should things be asynchronous?
Your nice spinner won't spin, since the UI will get blocked as well during the synchronous call. Sure, you can make the call on a separate thread, but then you're doing essentially the same thing as the asynchronous call.
i am getting confused what is the difference between Synchronous NSUrlConnection and ASynchronous NSUrlConnection?is there Synchronous or ASynchronous? if we use detachNewThreadSelector in connectionDidFinishLoading method,is it
ASynchronous NSUrlConnection? which is the best way?any tutorial ...
Synchronous means that you trigger your NSURLConnection request and wait for it to be done.
Asynchronous means that you can trigger the request and do other stuff while NSURLConnection downloads data.
Which is "best"?
Synchronous is very straightforward: you set it up, fire it, and wait for the data to come back. But your application sits there and does nothing until all the data is downloaded, some error occurs, or the request times out. If you're dealing with anything more than a small amount of data, your user will sit there waiting, which will not make for a good user experience.
Asynchronous requires just a little more work, but your user can do other stuff while the request does its thing, which is usually preferable. You set up some delegate methods that let you keep track of data as it comes in, which is useful for tracking download progress. This approach is probably better for most usage cases.
You can do both synchronous and asynchronous requests with NSURLConnection. Apple's documentation provides a clear explanation of the two approaches and delegate methods required for the latter approach.
It seems that you're conflating synchronous/asynchronous connections and threading. In my app I used asynchronous connections as an alternative to threading.
Let's say you want to download a big file without causing the UI to freeze. You have two basic options:
Asynchronous connection. You start with + connectionWithRequest:delegate: (or one of the other non-autorelease options) and it downloads bits of the file, calling your delegate when interesting thing happen. The runloop is still going, so your UI stays responsive. Of course you have to be careful that your delegate don't go out of scope.
Synchronous. You start the connection with + sendSynchronousRequest:returningResponse:error: but the code waits until the download is complete. You'll really need to spawn a new thread (or one of the higher level threading operations that Cocoa supports) or the UI will block.
Which option is "best" or the least painful will depend on the architecture of your application and what you're trying to achieve. If you need to create a thread for a long running process anyway, you might go with the second option. In general I would say the first option is easiest.
It's all pretty well documented on Apple's Developer site.
Something which hasn't been mentioned in the other responses is the size of the request. If you're downloading a large file, for example, then using an asynchronous connection is better. Your delegate will receive blocks of data as they arrive. In comparison, the synchronous method will wait for all the data before making it available to you. The delegate can start processing the response sooner (better user experience), or save save it to a file instead of memory (better resource usage). You also have the option to stop the response without waiting for all the data.
Basically, the asynchronous method gives you more control over the connection but at the cost of complexity. The synchronous method is much simpler, but shouldn't be used on the main UI thread because it blocks.
In response to the other answers regarding the file size: I think file size doesn't matter. If the server responds really slowly and you're loading data synchronous your UI still freezes, even if you're loading a small amount of data, like 3k.
So I'd go for the asynchronous option in every situation, cause you never know what you're going to get with regards to file size, server responsiveness or network speeds.