callbacks inside applicationwillterminate - iphone

I am trying to post some data before my application terminates. Iam doing this by genrateing sockets using CFStreamCreatePairWithSocketToCFHost and later on I have the callbacks for reading and writing.
But I am not able to post any data. It goes through all the functions but doesnot enter into callbacks. Does that make sense to anyone?. Is there anyway to get this working?
Thanks,
Sowri

Yes, after applicationWillTerminate is called, there are no more iterations of the run loop. Since CFSocket and CFStream both use the run loop to manage the sockets and to provide data via the callback, this will not work. Also, it's very important to note that the application may be restricted from doing certain things at this stage and that if your application does not terminate, the operating system will terminate the application. It may be a better idea to write a small log to a database and then post that information back the next time the application starts.

My gut feeling is that after the applicationWillTerminate method is done, it will just stop the whole app, without giving any other run loop the chance to execute, let alone do callbacks. So my guess is that calling asynchronous methods in the applicationWillTerminate won't even start. You're just too late at that point to start networking.

The applicationWillTerminate: callback is not the place to do any kind of critical operation because as the name implies, your application will terminate and it won't wait for your code to finish doing something.
What are you trying to post; if you explain why you want to do this we may be able to offer a better solution.

Related

Flutter: Will callback supplied to Timer get fired when application goes to background

In Flutter if I create a Timer, will the supplied callback get executed if the application is in background?
I think documentation is not clear on this or I might have missed it (please supply a link if you find it anywhere).
I just tried doing this with a timer set up to 10 seconds and it works fine.
I assume that is approach is not very reliable and other methods* should be used instead. I think if the app is paused/terminated by operating system to preserve battery or due to low memory, nothing will be executed. But for me this situation could be an ok approach.
* I know there are isolates so I guess I could spawn the timer inside one of these. Downside is that the isolate must be regular function (or static method) so no access to application data in my scenario. Then there are different scheduling packages etc but I'm trying to avoid these for now. I know about background tasks but I'm really looking for an answer on code execution using timers.

Correct way to poll a webservice in an IPhone app

I am trying to determine the best strategy to poll a webservice once a minute, parse the xml returned and then update an object stored in a shared instance. This process needs to run in a separate thread, and will continue as long as the app is running.
It seems that I could put all the code to call the webservice and parse the xml into an NSOperation and add that NSOperation to an NSOperationQueue stored in the app delegate as soon as the app launches.
Is it a correct approach to use an NSTimer inside the main method of the NSOperation so that the operation will loop once a minute, indefinitely? In that scenario the NSOperation would never actually return - this seems what I want but I am not sure if this is the right way to think about it.
The problem I am trying to solve is of course extremely common, so I am trying to figure out the correct way to implement it. Any advice greatly appreciated.
The real correct way to do it is to use push notifications. If any of your users have cell plans with limited data or data charged based on usage, they will thank you for it.
But if you insist on polling, you may as well use the NSTimer directly rather than messing with a timer inside an NSOperation. This will run on the main thread, but you could have the timer callback use performSelectorInBackground:withObject: to do processing in the background. Or you could just skip the timer altogether and run the whole polling sequence on a separate NSThread, and use sleepForTimeInterval: to delay between polls.
I would highly recommend you take a look at ASIHTTPRequest. What an amazing little class, and really well documented.
Edit:
Take a look at this answer for what seems to be the optimal solution.
one approach: create a thread and use a run loop, updating or idling as appropriate. then you can perform the request from the secondary thread and post it to the rest of the app after it's been parsed/prepped.
this way offers more control over pause/resume/delays/timing, and you can easily control the number of active requests (which should be exactly zero or one).
I wouldn't use NSTimer for this problem/design. I would create NSThread from the AppDelegate when the application starts. I would lower the priority of this thread. Inside the NSThread main method is basically a loop.
-(void)main {
while(true) {
// get raw data from url
// hash the result
// compare the hash to the last time
if (currentHash != lastHash) {
// post a notification to default center with the new data
lastHash = currentHash;
}
// sleep the thread sleepForTimeInterval
}
}
Your Model object would subscribe to the notification from the thread and parse the new data and updates ivars. Your View object would listen to the Model using KVO and display any updates/changes.

Send Network Message When iPhone Application is Closed

My iPhone application supports a proprietary network protocol using the CocoaAsyncSocket library. I need to be able to send a network message out when my iPhone application is closed. The code that sends the message is getting called from the app delegate, but the application shuts down before the message actually goes out. Is there a way to keep the application alive long enough for the message to go out?
Bruce
The docs from Apple don't specifically state this, but the sense I get from looking around the Web and from personal experience is that you have about 4 to 5 seconds after the user hits the Home button to shut your app before your application actually terminates. The iPhone OS is controlling this so you can't block the termination to allow your program to finish first. Basically when your time is up, your program is killed.
There may be another solution, though. First I'd confirm that your code is really taking more than 5 seconds to run. Perhaps you can have it run in response to a button tap, and time how long it runs. If it is more than 5 seconds, you probably are running into this time out issue.
You might then find a way to trigger a message to be sent from a server that is always running. You should have enough time to trigger a remote action, which in turn could then take as long as it needs to run.
Or perhaps you could save the vital information to the iPhone file system on exit, and send that message the next time someone starts the application, which should theoretically give you enough time.
Hope this helps!
I assume you're already calling it from your AppDelegate's:
- (void)applicationWillTerminate:(UIApplication *)application
But as you've discovered there's no guarantee it'll be called or will be allowed to finish. There are a few options that may or may not work depending on what you're trying to do:
If you need the server to perform some sort of cleaning operation triggered by when the client app is gone then you could try watching for TCP socket closure on the server and treating that as the triggering event. But if you explicitly need to send data back with the closure this may not work.
If the data you're sending back is not time-sensitive then you can do like most of the analytics libraries do and cache the data (along with a uuid) on the client then try to send it on app closure. If it goes through, you can clear the cache (or do it the next time the app is run). If it doesn't, it's saved and you can send out when the app is run next. On the server, you would use the uuid to avoid duplicate requests.
If the material is time-sensitive then your best bet is to implement heartbeat and send periodic updated values to the server. Then when the client app dies the server times out the heartbeat and can use the last received value as the final closing point of data.
In either case, if an explicit closure event is required by your custom protocol then you may want to reconsider using it in a real-life mobile environment where things have to be much more fluid and tolerant of failure.
As others have noted, there's no way to be absolutely certain that you'll be able to send this, but there are approaches to help.
As Ken notes, you do in practice get a few seconds between "willTerminate" and forced termination, so there generally is time to do what you need.
A problem you're almost certainly running into is with CocoaAsyncSocket. When you get the "willTerminate" message, you're on the last run loop of the main thread. So if you block the main thread, and CocoaAsyncSocket is running on the main thread, it'll never get processed. As I recall, CocoaAsyncSocket won't actually send all the data until the next event loop.
One approach, therefore, is to keep pumping the event loop yourself:
- (void)applicationWillTerminate:(UIApplication *)application
{
// ...Send your message with CocoaAsyncSocket...
while (! ...test to see if it sent...)
{
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
I've also looked at putting this work onto a background thread and letting the main thread terminate, in theory letting us go back to Springboard while continuing to run for a few seconds. It's not immediately clear to me whether this will work properly using NSThread (which are detached). Using POSIX threads (which are joinable by default) may work, but probably circumvents any advantages of the background thread. Anyway, it's something to look at if useful. In my apps, we've used the "post next time we launch" approach, since that always works (even if you crash).

what exactly NSUrlConnection ASynchronous means?

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.

Is there any sample code to do iPhone mulitithreading tasks?

I have some slow internet task to save and load file, I'd like to do those slow tasks in some background thread. I am wondering whether that's doable, and if it is, any sample code?
Then after it is finished, I'd like it to notice back to the main thread, so that I could update the UI.
Take a look at NSURLConnection. It will load an NSURL (using NSURLRequest) in the background, and send delegate methods regarding its status.
Ultimately the device you are running your code on has a single processor and cannot possibly load large quantities (gigabytes) of data. The best route, by is likely that suggested by Ben (NSURLConnection asynchronously) which gives you the added advantage of being able to cleanly cancel and handle error messages. While it isn't technically threaded in the way you probably think you want it to be, it is well integrated with the event loop and is non-blocking. If that is still not enough, I would suggest looking at NSOperation and NSOperationQueue. You can fire off an NSOperation sub-class object and perform the download there (I would still advise doing it asynchronously there so as to enable canceling, pausing, etc).
Log in to the iPhone Developer Center and search for Introduction to Threading Programming. Or, maybe you can log in and use this link:
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Multithreading/Introduction/chapter_1_section_1.html#//apple_ref/doc/uid/10000057i-CH1-SW1
If you do decide you need a background thread even after using asynchronous HTTP calls to gather the data, don't forget to wrap the background thread code in a new NSAutoReelasePool and then release it at the end.