I'm working on a iOS app where the user is fetching a reasonably sized database online, and then working with it offline. The update, and sync is taking around 10-15 minutes due to the memory constraints on the device and the way I'm handling the transactional inserts. All the while I have a dialog view open notifying the user of the progress, and give him the option of cancelling and reverting the changes to the database.
Anyway, today while testing I noticed that the iTunes app was trying to contact as server and do some background work, but threw an error:
itunesstored[68] <Warning>: Could not load download manifest with underlying error:
Error Domain=NSURLErrorDomain Code=-1001 "Cannot connect
to 112.168.198.2" UserInfo=0x1f8d6150
{NSLocalizedDescription=Cannot connect to 112.168.198.2}
This caused a dialog to display on top of the one I was already displaying, notifying the user that iTunes was unable to connect.
Now when I clicked the 'close' button, that somehow also closed my dialog, causing only parts of the actions, to be taken when the user decides to stop the update, to take place. The async update kept on going in the background, while the database tried to revert the changes causing the database to lock up and I needed to kill the process and restart the app and update. By design, that reverts everything if something terrible like this happens.
Now I noticed that I should make some changes in my code to make it harder for the database to lock up like that, and I'm working on that.
But what I want to know is: is it possible to forbid iTunes, or any other process for that matter, to do any work on the UI thread while a certain critical process in your app is taking place?
The behavior of the iTunes dialog cancel button, i.e propagating down into my dialog can't be considered normal or reasonable.
No, this is not possible. Apps should be coded in a way that accounts for these kind of interruptions. For instance, on an iPhone, what happens if a telephone call comes in? It's the apps responsibility to deal with it; the system will let the call come through irrespective of your "critical process".
In general, it sounds like your app isn't designed in the best way. For instance, 10 minutes to parse a database seems extremely long — how many records does this database have? You should be able to import databases with 100,000 records in a couple of seconds on the iPhone.
Related
I have a CLLocationManager contained in a singleton and I have added around a dozen regions to monitor. I am successfully notified of boundary crossings when the app is in the foreground/background. However, when I force quit the app, the location icon disappears and I am not getting any callbacks.
As far as I can see, this is intended functionality as of iOS7. Here is a reply I found to a similar question, in this case involving significant location change: https://devforums.apple.com/message/882691#882691:
If a user swipes up in the app switcher then the OS will not launch the app unless explicitly told to do so by the user. So no, SLC will not be launching the app, nor will silent notifications. The only thing that will launch the app at that point is the user tapping the icon. The intention here is that the user has expressed their choice of not having that app running any more for any reason, so we honor that.
In this situation, there's really nothing that you can do. The next time the user launches the app you can let them know that some of the data may be missing, although you really cannot tell whether there's missing data or not (i.e. you might have been killed by the OS in the background and the user may not have moved thereby not triggering any SLC notifications). My suggestion would be to gather the data you can within the policies of the OS and if the user has manually killed the app then respect that wish and don't do anything.
By all means, feel free to file a bug report if this change in behavior winds up causing problems for you or (especially) confusion for your users.
After iOS 3.2, Apple allowed us to keep running our application in background mode. Using the same concept, in my application I have downloading functionality implemented which runs over in background mode.
The problem is that whenever I force quit my app manually, (Double tap on home button > long tap on app icon > tap on cross button of app) as per Apple specifications. I am not able to track that event in code, hence I am unable to track my downloading data.
Because of that, my data is being lost. So how to track this and track/save data before it gets force quitted.
Reference: AppDelegate Protocol
As far as I know, there is no way to handle that event, since it kills the whole process immediately.
You will need to save your data periodically or just leave it like it is. User killing apps, should be aware of that he is killing apps.
track each 'chunk of data' as you receive it and you write it to disk. that way you don't have to rely on a shutdown event
Thats how ASI and AFN do it and thats how you could also manually do it using NSURLConnection directly.
On startup, see if and how much of the data you already have in the file. Again ASI and AFN make this really easy!
I'm planning to release a new app in the future.
I have a custom logging function which logs some application data (not crashes) into a file (location manager state, app foreground-background transitions, main actions...). These logs helped me a lot to debug problems which were app-related, but not causing a crash. Until now these were in the documents directory (shared in iTunes) and the testers sent them to me after they saw some incorrect behaviors, however I don't want to share them anymore because this directory contains the app's database too.
I'd like to obtain these logs even when the app will be on App Store, but I don't know how this should be done. As I wrote, it is a new app and even after the test phase may exist minor bugs. I know that the users can report problems in iTunes or on the Dev site, but without a detailed scenario or log it is really hard to correct a bug. Should I make some kind of in-app bug report functionality (even if this creates a wrong user impression) ? How is this usually handled ?
Edit1 : I'd want these logs only if the user thinks something went wrong and should be analyzed, otherwise I don't really need them. I think some kind of user action is needed to confirm that something isn't working as intended, that's why I asked about making a functionality ( like the "Report a problem" in the Maps App ).
Thanks
If your app is gonna crash, don't submit it to AppStore because more likely it will be refused.
I don't know your app but usually logging slow down things. But if you really want logging I would suggest you to first find out if application crashed. For instance in your appDelegate when the app is terminated without problems set some NSUserDefaults value like closedSuccesfully=YES. Just after you start app set closedSuccesfully=NO, but if it was set to NO before it means your app crashed last time. In that case you could grab your previous logs and try to send them to your server via http post message. On your server there might be very simple php script to get that data. That way it will be automated and your users wouldn't have to do anything and you would get all crashes even these not reported.
I have developed an application. My application takes feedback from users. When network is not available, then that data is saved in local db. But, once the network is available, it will sync automatically with the central database.
But, I have some problem here. If I save database & send my application to background, once the network is available, it has to automatically do this syncing with the central database. How to do that?
I am using Reachability class to check network availability.
At the present time there is no way to have your app "wake up" when the network becomes available. If the user quit your app without a network connection, you cannot do anything until they voluntarily open your app.
However, you can prompt them to do so using UILocalNotification. If your app is being quit and you have some data waiting to be uploaded, you can schedule a notification to fire in 4 hours (or whatever amount of time makes sense).
If the user opens the app before the notification time and you are able to upload the data, you can cancel the notification and no one will ever know it was scheduled.
If the user does not open the app, the notification will appear, and say something like, "You have data on your phone that you have not uploaded in a while. Connect to the Internet and launch MyAwesomeApp to sync your data."
You cannot do it on iPhone. Your app ceases to exist in a few seconds (once the app moves to the background).
I believe its 5 seconds for all apps, 10 mins for some apps that have requested for more background time.
PS: Unless, you mark your app as a navigation or a music app, which can stay on in the background, theoretically, forever. But I doubt if a feedback app can get approved on the appstore with such permissions.
Keep an additional column in your saved database which marks successful uploading of your data to your server. Set this when the data is written, but not yet uploaded. When it's successfully uploaded, clear the value. You can check this value when your app comes to the foreground, and have it upload any data that hasn't had this column cleared. While your app is running, you can set a timer for an appropriate interval to recheck reachability and if successful, attempt an upload. Only clear your flag when the data is successfully written, and make sure your server doesn't try to process a partial upload (think of someone trying to do this on a subway or train, moving in and out of connectivity).
I am trying to determine feasibility of certain features required in a (potential) project. I am not (yet) looking for a how-to, just a can-do. I apologize for any vagueness and ignorance: the former due to an NDA that makes Apple's NDA look like GPL, and the latter due to the fact that I have no iPhone or MAC experience.
I do have a solid understanding of objective-c and interface builder (going back to NextStep) and some PDA development experience, so I'll probably understand the answers, even if my questions are naive. I have done a bit of browsing, so I know some buzzwords.
I can't go into detail about the actual project, but I have come up with a lame analogy.
a large number of users in the same room are asked to complete task(s) in the app (say a puzzle)
they are under supervision, but the monitor cannot watch them all closely
they are not allowed to leave the application until done.
they cannot send/receive phone calls or messages during the task.
the monitor receives notification of various steps during the task
the monitor is notified when the task is completed, or the app is exited
the app sends a heartbeat, so the monitor also knows if signal is lost
Jailbreak is not an option.
The app should also work on iPod Touch.
So the things I need to do that seem dicey to me are
can I turn off (or require the user to turn off) phone and sms but still be able send http to my server
can I prevent an app from being switched out (even if, say an alarm app triggers or the phone rings).
failing prevention, can I at least detect any of these events and notify my server.
failing notification, can I record the event for the monitor to check later.
The user will be aware (and in fact welcome) these restrictions. It's a trust issue - the user must not seek help or use a helper app to solve the puzzle, and wants the monitor (and other contestants) to know that he did not. It's feasible for the user to click on an "OK, I understand and approve" screen at the beginning, but not for each communication to the server.
The app would only communicate with a central server (run by my company) - the monitor would not be able to buy the server software, and the url's of the server would not be user (or monitor) modifiable.
Hey! This looks like an app for taking exams. Not what I am doing, but that would be cool too!
EDIT --
I changed the title and am adding a few more parts to the question, based in part on mmc's answer. The App may run in an offline mode that would have to do the following:
So using the exam analogy, the user off line experience would be something like this
Launch App
App download test questions, registers start time, etc.
Turn off phone (if app can't do it by itself)
Disable any app that might interrupt my App (can app do this?)
Resume and Take Test
Indicate test done (or finish last problem).
Turn on phone (if app can't) and restart App (if needed).
App uploads test results and log of any interruptions.
So the question becomes
Am I sure that I at least get to log any interruption I can't prevent
can I know the cause of the interruption (phone answered, alarm launch, user initiated)?
can the user be prevented from modifying the log
can I know what other Apps are running when I start? (to guard against a daemon that occasionally displays a hint or something.
I would still like to run with real time uploads, so a few other ideas come to mind.
If I can reliably detect and record that the phone or another app was used, that might be almost as good as preventing it.
Can the user prevent the phone from ringing even if it's on (eg. call forward + ringer off)
Can my app know if the ringer is off
Same question for sms messaging
If I can't block it, can the user just ignore (silent) call or message and not leave my App. Would my app know that?
Sounds like you might be better off doing away with the phone, and making it exclusive to the iPod Touch.
You've nailed your trouble spots.
There is no way to disable phone functionality, and at the same time maintain network functionality of any type (3G, WiFi, or bluetooth) If you disable the phone operations with Airplane mode, all of them are disabled.
There is no way to prevent the Home button from returning you to Springboard
You can notify a server of a premature app interruption (there is an applicationWillTerminate: method on your app delegate) but is not reliable. If the operation takes too long, your app will be forcibly terminated.
You could write to the local file system that a premature interruption happened, and this would be far more reliable, as this operation would be much faster.