I have an app with dynamic data and the update method uses arrayWithContentsofURL and dictionaryWithContentsofURL to get the plists from a server in order to update my database.
My problem:
When there is no or not correctly working internet connection on the device this request simply tries to get the data for about a minute before it stops trying and continues execution.
Is there a way to maybe set a timeout for this function?
PS: I know this is probably the worst way to do this and I would be happy if someone could point me in the right direction :) I'm quite new to iOS programming so please be patient.
In my opinion it's best to use an NSMutableURLRequest with it.
Which has a - (void)setTimeoutInterval method. From the documentation:
The timeout interval, in seconds. If during a connection attempt the
request remains idle for longer than the timeout interval, the request
is considered to have timed out. The default timeout interval is 60
seconds.
Suggest you use an NSURLRequest to send the Request object. Its delegate functions will return you the plist.
You could take this example, about half way on that page it downloads a json object very much the same way as you could fetch a plist.
Related
We set timeout interval for a request by NSMutableURLRequest timeoutInterval. As Apple's document described, it specifies the limit between packets, not the whole request. When we analyse our requests logs, some timeout request exceeded the seconds we set to timeoutInterval. We need timeout the requests accurately.
By reading document and blogs, the timeoutIntervalForRequest property in NSURLSessionConfiguration is the same as timeoutInterval. But the timeoutIntervalForResource property seems fit our requirement.
However, Mattt says in objc.io that timeoutIntervalForResource "should only really be used for background transfers". Can it be used in normal request? Such as query user info. Is it appropriate in this situation?
Thanks very much.
It can be used, but it rarely makes sense to do so.
The expected user experience from an iOS app is that when the user asks to download or view some web-based resource, the fetch should continue, retrying/resuming as needed, until the user explicitly cancels it.
That said, if you're talking about fetching something that isn't requested by the user, or if you are fetching additional optional data that you can live without, adding a resource timeout is probably fine. I'm not sure why you would bother to cancel it, though. After all, if you've already spent the network bandwidth to download half of the data, it probably makes sense to let it finish, or else that time is wasted.
Instead, it is usually better to time out any UI that is blocked by the fetch, if applicable, but continue fetching the request and cache it. That way, the next time the user does something that would cause a similar fetch to occur, you already have the data.
The only exception I can think of would be fetching video fragments or something similar, where if it takes too long, you need to abort the transfer and switch to a different, lower-quality stream. But in most apps, that should be handled by the HLS support in iOS itself, so you don't have to manage that.
We're converting our CURL HTTP Get requests to native IOS code. With CURL we can set two different timeouts - CURLOPT_CONNECTTIMEOUT - how long before a call fails if it cant connect, and CURLOPT_TIMEOUT - how long before a call fails if all the data hasnt been retrieved. If the connect fails we want it to return pretty quickly (10 seconds), but we download large chunks of data possibly on slow connections so we need the completion timeout to be quite large (5 minutes).
How do we set different timeouts using NSMutableURLRequest
Currently we are setting the single timeout like this
[urlRequest setTimeoutInterval:30.0f]
Is there a way to set two separate timeouts, like CURL does ? And which timeout are we currently setting ? The connection timeout or the completion one.
Thanks
shaun
That's a really good question. The documentation on it was unclear to me:
If during a connection attempt the request remains idle for longer than the timeout interval, the request is considered to have timed out. The default timeout interval is 60 seconds.
I did find this really helpful post in the Apple Developer Forums, which an Apple employee explains:
The timeoutInterval property is equivalent to
timeoutIntervalForRequest property.
He's referencing the property on NSURLSessionConfiguration, which can be attached to an NSURLSession. If you set the timeoutInterval of an NSURLRequest, it is used as the value for timeoutIntervalForRequest on the configuration. This property's documentation does provide some insight:
The request timeout interval controls how long (in seconds) a task
should wait for additional data to arrive before giving up. The timer
associated with this value is reset whenever new data arrives. When
the request timer reaches the specified interval without receiving any
new data, it triggers a timeout.
The default value is 60.
Based on that, it seems this value is actually neither!
I am trying to find out the duration and if it is possible the latency of a network call to an iOS native application. I already found the instruments tool and tried out different templates without success :(
To be more specific i want to get the duration of a call that is send over a glassfish server which runs on my local machine. The call sends a json object.
I hope you guys can help me?
Thanks
I think you can use NSURLConnectionDelegate method here, if you are using NSURLConnection to send the request to your server.
When you set up the request, you can use
CFAbsoluteTime before = CFAbsoluteTimeGetCurrent();
to get the exact time when you initiated the request.
Use Delegate method
connection:didReceiveResponse:
and inside it
CFAbsoluteTime after= CFAbsoluteTimeGetCurrent();
difference between after and before will give the exact duration.
Also use, connectionDidFinishLoading:
if you want to get the time when you have completely loaded the JSON response.
I have a JSON database connection for my app, and it is set to load (refresh) on the app's initial launch. The JSON data is stored on the phone, and retrievable if no internet connection is discovered on relaunching the app--so there's always data in there.
If the user has a slow connection to the internet--as in patchy <3G--the app will hang. I would like to set a timeout that reverts the database to the saved information (as it would if there were no connection at all). Unfortunately, I think that setting the timeout in the wrong function could make the app crash.
I've read there's no publicly available class to determine a connection speed, but can anyone suggest alternatives?
You could set a timeout for the NSURLRequest, if thats what you're using. In the callback that handles the timeout you could fall back to your local copy of the data. Check the following answer provided by another user.
NSURLConnection timeout?
If you wanted to determine the actual connection speed, you could have your app download a piece of arbitrary data of fixed length, and record the time it takes to complete. This has its own flaws though. You would have to decide when to do this, and how frequently. It may also suffer from the problem that you are trying to solve. And, for example, if the user was on a train, their connection may be great one moment, and poor the next. I think that the timeout solution would work ok, it just means that the user has to wait a period of time before the app falls back to the local copy of the data.
OK - let's rephrase this whole question shall we?
Is there any way to tell if iOS is holding onto an NSURLConnection after it has finished & returned it's data?
I've got 2 NSURLConnections I'm instantiating & calling into a server with. The first one initiates the connection with the server and then goes into a COMET style long-polling wait while another user interacts with the request. The second one goes into the server and triggers a cancel mechanism which safely ends the first request and causes both to return successfully with a "Cancelled by you" message.
In the happy path case the Cancel button will never be clicked. But it's possible to click it and exit the current action.
This whole scenario works GREAT once. And then never works again (until the app is reset).
It's as though the first time thru one of the connections is never released and we are from then on limited to only a single connection because one of them is locked.
BTW I've tried NSURLConnection, AFNetwork, MKNetworkKit, ASIHTTPRequest - no luck what-so-ever with any other frameworks. NSURLConnection should do what I want. It's just ... not letting go of one of my connections.
I suspect the cancellation request in Step 2 is leaving the HTTP connection open.
I don't know exactly how the NS* classes work with respect to the HTTP/1.1 recommendation of at most two simultaneous connections, but let's assume they're enforcing at most two connections. Let's suppose the triggering code in Instance A (steps 1 and 3 of your example) cleans up after itself, but the cancellation code in Instance B (steps 2 and 4) leaves the connection open. That might explain what you are observing.
If I were you, I'd compare the code that runs in step 1 against the code that runs in step 2. I bet there's a difference between them in terms of the way they clean up after themselves.
If I'm not wrong,
iOS/Mac holds on to a NSURLConnection as long as the "Keep-Alive" header dictates it to.
But as a iOS developer you shouldn't be worried. any reason why you would like to know that?
So unfortunately with the lack of a real solution to this issue being found in all my testing I've had to implement simple polling to resolve the issue.
I've also had to implement iOS only APIs on the server.
What this comes down to is an API to send up a command and put it into a queue on the server, then using an NSTimer on the client to check the status of the of the queued item on a regular interval.
Until I can find out how to make multiple connections on iOS with long-polling this is the only working solution. Once I have a decent amount of points I'll gladly bounty them away for a solution to this :(