I'm using SBJson to retrive data from URL. How to check if I have access to the URL before downloading. I want to check this, sometime application crash if there is no network connection.
Here is my code
id response = [self objectWithUrl:[NSURL URLWithString:#"http://myurl.com/Service.svc/GetId"]];
*I'm using stringWithUrl and objectWithUrl method to download the JSON.
Use the Reachability API and use that URL as your hostname you are testing
http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html
//reachabilityWithHostName- Use to check the reachability of a particular host name.
+ (Reachability*) reachabilityWithHostName: (NSString*) hostName;
Do NOT use Reachability on the main thread to detect whether you have a network connection. It doesn't work and can lock up for 30 seconds or more, causing your app to be terminated.
Instead you should simply try downloading the data using an NSURLConnection -- this will power up the radio(s) if needed. You will get a callback if an error occurs.
All network connections -including domain name lookups- should be on secondary threads or asynchronous or at least nonblocking. In the case of NSURLs, use NSURLConnection's asynchronous callbacks.
Your application is probably crashing because you are are making a network call from the main thread and locking up for more than 30 seconds, so the system watchdog timer kills you. Looking at your crash logs in Xcode should verify that. Otherwise, you probably just aren't handling the error condition properly.
Related
I'm setting up a class to manage the download of some data. Due to the spec it has to be downloaded multiple times (as it may change). I can't change that but I have a question.
If I create a class that is dedicated to downloading the data so it is an NSURLConnectionDataDelegate etc...
Can I store the NSURLConnection as a property and set it up in the init and then reuse the same connection each time?
Or should I store the NSURLRequest and use the same request in a new connection each time?
The reason I ask is that the docs for NSURLConnection state...
"You cannot reschedule a connection after it has started."
and I'm not 100% sure what that means.
Yes, as long as each time you have a unique object that creates the NSURLConnection. This is simply stating you can't have the same object "reschedule" a connection, mid connection.
Never hurts to run a simple test.
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)
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.
I am a little confused on how to go about and do this....
On each page of my app i connect to PHP file to drag in data from my server. I have about 10 pages. Now if there is no connection to the internet then of course now data can be received.
Often the app crashes and we are putting this down to not having the data due to a change in connection or wifi whatever.
Now i have setup the reachability thing and that works, but i dont know how to link this in with the PHP calls. Should i check the reachability and if no connection then dont run the call. If so, what about all the variables, they will still be null and cause an error then?
I dont really know what is the best solution.
Hope you can help
Alex
Are the php calls just to receive data from a database without using a built in DB framework such as SQLite? If so, I went the same route to avoid the headache at first, but running SQLite in your app is a better solution overall, and reduces multiple dependencies (such as internet connection).
Now if the php calls that give you data back are receiving this information from yet another source and then feeding it into its own DB.....
Should i check the reachability and if no connection then dont run the call
Yes you should. This is done in multiple apps already. What variables would be null in this case? Pop the code that makes the call in an "if" block below this check, and only run it if true. Error handling other variables that might be null because the php call isn't setting them is up to you. You can do this is multiple ways.
You should certainly cache the data so the App doesn't HAVE to connect to the internet to display something, other than that I would make sure to use asynchronous requests and the timeout feature of NSURLRequest to control your attempts to request data in the background. If you don't get the data, just keep using what you have cached.
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