Maybe you could help me to find the appropriate way to handle this :
I have a NSTimer (started in my AppDelegate) which fires a class to launch a asynchronous server request (I use ASIFormDataRequest)
When HTTP JSON-response is received, I parse it using TouchJSON
Then I loop the NSDictionary obtained to fill a dedicated NSManagedObjectContext
Then I save this context on some user interactions
Sometimes the HTTP request is sent and the user quit the application. I want to get extra time in order to complete tasks 2 to 4 in background.
I read the Apple doc but it is still not clear how to gain extra time for an asynchronous action already started ?
In short, how should i use the beginBackgroundTaskWithExpirationHandler ?
Thanks for your very usefull help.
Kheraud
ASIHTTPRequest supports running requests in the background:
[request setShouldContinueWhenAppEntersBackground:YES];
If you do steps 2-4 inside the delegate notifications and set the above flag then that should do what you want.
You won't be able to interact with the user once your application has entered the background though.
Related
Sorry to bother with yet another NSURLConnection question, adding to the over one thousand already here.
The scenario is as follows. In an iPhone app using dynamically loaded augmented reality features, the user is prompted to download new AR models as these are made available. The models can be several MB large, so the user should be given an indication of the total size of all models to be downloaded before deciding to do so.
To find out how large each file is I want to use an asynchronous NSURLConnection but then to stop the download once I have got the response ([NSURLResponse expectedContentLength]). I can do this in the delegate's connection:didReceiveResponse: method.
My question is, how can I wait until this condition arises? How can I setup the NSURLConnection, let it start asynchronously and then wait until the connection:didReceiveResponse: method is called? I have tried using a NSCondition, letting this wait after setting up the NSURLConnection and in the connection:didReceiveResponse: method signalling the condition. But all this did was to freeze the main thread. Any ideas?
Maybe you could send a HEAD request instead of GET. This may depend on your server set up, but that should get you just the headers, including Content-Length. You ought to be able to use a NSMutableURLRequest so you can change the request method, and then read expectedContentLength on the response as usual.
What would be the most appropriate way to chain asynchronous NSURLConnections? For example, I need to register a user with a web service. The workflow would be as follows:
Get Register Token => Use token to Register => Get Login Token => Use token to Login.
I know how to create an asynchronous NSURLConnection, but I'm unsure how to make sure the previous connection has finished before moving on. I know I can achieve this using NSURLConnection sendSynchronousRequest but I don't like my main thread being blocked while these chained requests happen.
We did EXACTLYA this when we built our first version of SignMeOut for iPhone. We created a subclass of NSUrlconnection and gave it an identifying tag do in the connectionDidFinish you would be able to use a simple switch/case with an enum. Works great - you can see the whole flow and example and code in our blog
http://www.isignmeout.com/multiple-nsurlconnections-viewcontroller/
UPDATE
I've modified the NSURLConnection subclass into a much simpler Category. Most of the usage is the same but cleaner using the same class
https://github.com/Shein/Categories
You can look at connectionDidFinishLoading to start another asynchronous connection. For the conditions as to which connection ended, you can keep references to the connections in case other connections are also expected to finish(probably not needed in your case). Make your class follow the NSURLConnectionDelegate and fire the appropriate connections in the connectionDidFinishLoading delegate method. You can also use the connectionDidReceiveData: method to check for credentials, etc received from the service. Go through the documentation too.
You have different options:
create a queue using a mutable array or dictionary
create an NSOperationQueue kind of easy if you use it in combination
with the new only ios5 API for NSUrlConnection
third parties lib such as AFNetworking
Block GCD grouping them (hard for NSRunLoop reasons, pay attention in wich thread the connection is running in)
I'm working with an iPhone developer on an application. I know very little about the iPhone. I'm writing the server-side code in Grails. I'm wondering what is available to me as far as approaches to using a RESTful JSON service with an occasional poll of the service.
From the iPhone:
Is there a way to put these calls on a background thread? when the data comes back is there a callback mechanism? Looking for some basic information on how to accomplish this on the iPhone / Objective-C.
Yes, typically you either provide a delegate that is notified when an asynchronous request has some kind of event (e.g. more data comes in, the request fails, etc.), spawn a background thread that performs synchronous requests, or pass success/failure blocks to an asynchronous request that executes them when appropriate.
But if you are working with an iPhone developer, shouldn't he be dealing with this, not you?
Have a look at NSURLConnection. It automatically puts the request on a background thread and has some callback methods that get called on its delegate.
I prefer using the ASIHttpRequest library for my integrations with RESTful rails apps. One of many advantages is the completion block:
request.completionBlock = ^{ NSLog(#"I'm finally complete!"; };
[request startAsynchronous];
I needed to download some files when buttons on tableViewCells are clicked.
I was thinking of adding them to an ASINetworkQueue so that the download can happen.
However, when I came to tracking progress, it appears to me that they are saying that I can have only ONE PROGRESS for the ENTIRE QUEUE.
Is this true, or is there a way that I can track the progress of each request individually?
I need to have a custom tableview which shows how much of each file has been downloaded.
also, on a not-so-related note, can i set the
[request setShouldContinueWhenAppEntersBackground:YES];
for requests INSIDE the network queue?
I need to have support for background downloading, and if networkqueue does not support it, i might as well chuck the idea right now and look for some other way.
The documentation mentions:
Each ASIHTTPRequest has two delegates
that can be used for tracking progress
- downloadProgressDelegate (for downloads) and uploadProgressDelegate
(for uploads).
You can still use these delegates on the request, even if the request is part of a queue.
The network queue is just driven by events coming from the requests themselves (and the requests continue to be part of the queue even if they're running in the background). I believe that if you mark the requests to continue in the background then the queue events will continue too.
I have an iPhone app which uses ASIHTTPRequest to communicate to a REST service on my server. When I'm running on the simulator, it works just fine, but when I get onto the phone itself, I get weird behavior.
The very first time I click the button that initiates the request, I get the results back immediately, and all is fine. From that point on, when I click the button to initiate the connection it takes about 2-3 minutes to connect. It almost seems like the ASIHTTPRequest that I kicked off first (and from which I've already received the correct results) has not completed. Is there some sort of magic I need to use to terminate the original request before starting the next one? I assumed that since the -start method returned, and I have results from the server that the original request was completed and I could start another.
Any ideas?
Thanks
--Steve
Steve - What you've described is a common problem that will occur if the requests are attempting to keep a persistent connection. Try this out:
[request setShouldAttemptPersistentConnection:NO];
You're not suppose to call the -start method, it belongs to the NSOperation. The ASIHTTPRequest interface is either -startSynchronous or -startAsynchronous.
However, it's highly recommend to use the asynchronous call otherwise, your main thread (ie., UI) will be blocked.
From the ASIHTTPRequest documentation[1]
In general, you should use
asynchronous requests in preference to
synchronous requests. When you use
ASIHTTPRequest synchronously from the
main thread, your application's user
interface will lock up and become
unusable for the duration of the
request. Synchronous requests are only
really suitable for software without a
UI (like a script that runs from the
terminal), or if you are running the
request from a separate thread that
you maintain (perhaps from inside your
own NSOperation, for example).
[1] http://allseeing-i.com/ASIHTTPRequest/How-to-use