In my iPhone app, I am downloading files from server and storing them locally (user's document directory). The path of each file downloaded is subsequently updated in database.
If user tries to delete a file, first the file is deleted from local path using removeItemAtPath: (NSFileManager), then corresponding record is deleted from database.
Now I have one of the requirements according to which user can turn on a UISwitch to delete all data on app exit.
Now my question is -
suppose user downloaded 20000 files, say small images, and user turned
on the switch to delete all data on app exit. Is it good to handle
this task in applicationWillTerminate? What is the best way to
accomplish this scenario?
Please suggest.
Don't delete the files individually, delete and recreate the folder.
Your database could be handled differently by version tagging so that you can batch delete the items on the next run.
applicationWillTerminate will only be called if your app goes background (the only option by pressing Home button of the device) and "Application does not run in background" key is set in your app's info.plist file to "YES". Otherwise it won't ever be called.
If you are planning deploy app with similar functionality, you can use applicationWillTerminate for removing so many files. However, I would never recommend you that. Instead, my recommendation is to remove the files as soon as they are processed, if possible at all.
Another thing you must consider is not to save so many files in Document directory, however small those are. Document directory is backed up by iTunes and iCloud and if you store so many files there, you are gonna possibly violate Apple's Data Storage Guideline that would reject your app from App Store. It is always a good idea to store transient files in application's "tmp" directory and delete them when not required anymore.
Related
Currently i was saving my application data (Media) to the CacheDirectory i.e
/var/mobile/Applications/BEAFC76C-C450-4A3A-9765-A0385A9580F3/Library/Caches
and things were going fine. But recently i got a bug report that the application data has been deleted. When i searched over it, i got this Apple Doc. According to it, DocumentsDirectory should be the ideal place to store the User/Application data.
Put user data in the /Documents/. User data is any
data that cannot be recreated by your app, such as user documents and
other user-generated content.
And Cache should not be used to store the User Data that could not be reproduced by the application.
Put data cache files in the /Library/Caches
directory. Examples of files you should put in this directory include
(but are not limited to) database cache files and downloadable
content, such as that used by magazine, newspaper, and map apps. Your
app should be able to gracefully handle situations where cached data
is deleted by the system to free up disk space.
What should be the ideal place to store it.
EDIT:
I have an application that allows user to store Videos and Photos in the application. For that i used CacheDirectory. But i am getting bug reports that the Data (Videos/Photos) is getting deleted. What conclusion i draw is that the data is being getting delete by the Device itself in order to provide space.
Secondly i also wanna give the iTunes sharing function. So only the particular files has to be stored in the DocumentsDirectory. Some files can never be exposed and some has has to be shared. What should be the ideal way to store the files.
Use Documents (NSDocumentDirectory) for files you wish to share via iTunes.
Use Application Support (NSApplicationSupportDirectory) for files you wish to hide from the user but still be backed up and never deleted by the OS.
Starting iOS 5, Apple says that it's no longer a good thing to save all kind of files in Documents Directory - if you do that, your app will be rejected for sure because this folder is backed up to iTunes & iCloud, unless otherwise specified.
It says that we should save files into Caches or Tmp Directory - these won't be backed up, but it's not a good thing to do because files from these directories can disappear if low memory happens.
So I think the best think to do is to save the important files that you need all the time in your app into Documents Directory and mark them not to be backed up, like this.
Library/Application Support Folder is the folder you should be using.
This directory doesn't always exist, and thus you may need to create it.
You can enable or disable whether you want to backup this data with iTunes or not.
This data is not accessible even if you enable file sharing. Only data that you put in Document directory would be shared with iTunes sharing, so you can still protect your data and get it backed up as well. Apple's documentation
Is it possible to make it so you can only 'Save To...' in the iTunes File Sharing? I want the user to be able to export files from the app, but not be able to add/import to the app on the device. Does that make sense?
I have tried googling it, but can't find any articles on it.
No, there is no way to make the file sharing only one-way. If the user can save a file, a user can also add, delete, and rename files.
Keep in mind that the user can make such changes without the device even being connected. The next time the device does a sync, the files will be updated.
You could make existing files read-only. That should at least prevent deletions and renames but not additions. Of course your app can detect the additions and simply delete or ignore the new files as needed.
my app has been rejected due to iCloud Storage Restrictions. (2.23).
There are lots of questions for this situation, but i am still not sure why my app has been rejected.. Here are my suspects:
1- My app downloads pdf files and images for letting users see on "offline" mode when a user selects a row from a tableview. I've set my download folder as "Documents/privateDownloads" and set the folder (and files inside) url flags as "do not backup"
2- My app also has a 2Mb. "preload.json" file, which my app reads the file at first launch and preloads into the database only at first launch (with a progress hud showing the progress of importing data). I haven't set the "preload.json" file as "do not backup".I just drag dropped the file into "Supporting Files" group in Xcode.
My guess is the problem lies in the 2nd suspect, but i've also read that i should move the "privateDownloads" folder into "Application Support" Folder instead of Documents folder.
i always stored my offline files on nsurl cache for a very long time (technically forever), but this time i've decided to do like this.
thanks for reading and helping.
Edit: there is a note from app store for rejection reason:
"In particular, we found that on launch and/or content download, your
app stores 3.6MB"
When i control this issue, this is happening after my application "preloads" the data. But what i really don't get it is, i am storing this preloaded data in core data. So yes, i want this data to be backed up in iCloud?!
To solve the issue of your seed data being too large, you might split your Core Data stack in two separate stores - one which stores the user data and is backed up to iCloud. And a second one which stores the seeded data imported from your JSON. This store could then be excluded from iCloud backup via the "do not backup"-flags.
Another recommended way would be to ship a pre-populated store like described in this article on objc.io. Since you mentioned your preload.json is several MB, this would be even more desirable to pre-generate the store once than on every device on initial app startup. And you could apply the required file attributes for not backing it up more easily.
The issue won't have anything to do with your preload.json file. If that's included in your app distribution, it is part of the app and you don't need to do anything different with it.
I would suspect that the reviewer didn't notice you were setting the 'do not backup' flag on files you've added to the Documents/privateDownloads folder, or that you have a bug and the flag isn't being set at all. It is safer, if you're able, to store those kinds of files in a /Library/Caches sub directory. Then you don't need to worry about the flag.
I have a SQlite database file with records which comes with my app.
I just used the file I added to my project to make my INSERT and UPDATE statements.
After uploading it to my test device I got the exception that the file is read only.
After a bit of research I found out, that I have to copy the db file to the users directory to make an insert. This works for now. But I have a view questions about it, which i didn't get answered through google:
Where should I put my copy process?
I implemented it in the AppDelegates FinishedLaunching, where I check if it already exists.
Where should I copy the file to?
I used the MyDocuments folder for now, is this ok?
Since the file cannot be encrypted, can another app access the database file?
When the user decides to delete the app from the device. Will the database file get deleted,too?
Thanks!
Where should I put my copy process? I implemented it in the AppDelegates FinishedLaunching, where I check if it already exists.
That really depends, but finishedLaunching is OK from my point of view.
Where should I copy the file to? I used the MyDocuments folder for now, is this ok?
I'm not sure what you mean by "MyDocuments" folder. Each Application has a dedicated Document directory. That's where you should copy it.
Since the file cannot be encrypted, can another app access the database file?
No, they run sand-boxed (unless the device is jailbroken)
When the user decides to delete the app from the device. Will the database file get deleted,too?
Yes, since the whole document directory will be deleted.
Where should I put my copy process? I implemented it in the AppDelegates FinishedLaunching
Keep in mind that you have a limited amount of time to complete FinishedLaunching execution (around 15 seconds) before the iOS watchdog kills your application.
Depending on the size of your database, the speed of device and other processing you need to do then you might want to consider only checking if it already exists (that should be quick) then do the copy (if required) from to another thread.
I used the MyDocuments folder for now, is this ok?
Yes, using Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments) is correct.
Everything else from #Lightforce answer covers the rest.
I have a simple app that downloads some data from a webservice and displays it in tableviews. In order to allow offline access, the app caches this data in the cache directory on the device itself. I keep a list of all of the cached files for reference, and save that to the cache directory as well. So after all of the downloads are complete I have the following files:
XMLFileList
XML1
XML2
...
I launched this app a couple weeks ago, and have since had to release a few minor updates as necessary to fix some minor bugs. It seems, however, that when a user updates the app on their device, they no longer see the downloaded resources. I have managed to get this to happen on a development device, by updating through the app store, then loading a debug build, and determined the following problem
It would seem that it is not displaying the data in the downloaded files because they no longer exist. It is also not re-downloading the files because they show up in the saved list. This provides a rather interesting question: why did the cached XML files get deleted, but not the master list?
What exactly is going on behind the scenes during an app update that I could account for, or reproduce to ensure this does not continue happening?
If you're putting files into /Library/Caches (or whatever it is), then there is no guarantee that those files will be there the next time you run your app. Anything you put into /Documents, however, will be there. And in fact, anything in /Documents will also be backed up to iCloud (unless you set the bit newly available in iOS 5.0.1 that lets you opt-out files in /Documents from being backed up.)
Anyway, the point is that you should read Apple's docs on what files you should put where. (I searched around for the correct reference unsuccessfully; I've seen it before though.) It boils down to this: Anything that is user generated should go in /Documents, anything that can be re-fetched from a server should go in /Library/Caches and may be purged by the OS.
Cache directory contents are not guaranteed to be preserved. But I don't see any documented guarantee that the entire directory will be cleared all at once. (Maybe only the biggest and/or oldest contents or some such?)