I've a simple question to the document directory. I build the folder by the following Swift statement:
open static let DOC_FOLDER : String = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).path
I store some files and create subfolders there.
And now I'm not sure whether the whole folder structure is deleted automatically if I uninstall the app or does the directory still exists and is only not accessible?
When the user uninstalls the app, the entire sandbox is wiped clean. If the user installs the app again, your app will need to recreate the folder structure again.
Put user data in Documents/. User data generally includes any files you might want to expose to the user—anything you might want the user to create, import, delete or edit. For a drawing app, user data includes any graphic files the user might create. For a text editor, it includes the text files. Video and audio apps may even include files that the user has downloaded to watch or listen to later.
=> If you uninstall the app, the folder will be removed
Reference: https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html
https://developer.apple.com/library/content/technotes/tn2406/_index.html
Related
now, I have DB Data being used on Linux and Window.
I'd like to put it in the iPhone, and use them in my iOS Application.
How to put DB in Sandbox area of my iOS Application ?? And where is the path?
Generally you’d use FileManager method url(for:in:appropriateFor:create:) to build a file URL:
let fileURL = try! FileManager.default
.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("test.sqlite")
So, if you had a blank database in your bundle, you’d copy that initial copy of the database to the above file URL, and then open it using this URL from that point on. Or if you were programmatically creating the database from scratch, you’d again use this resulting file URL.
But don’t save this absolute path anywhere. Always build it programmatically like above.
Note, historically we used to use the .documentsDirectory for things like this (and you’ll see lots of those sorts of answers lingering about on the web). But nowadays we would use the .applicationSupportDirectory. See iOS Standard Directories: Where Files Reside document or the iOS Storage Best Practices video.
We plan to store the following user files
SQLite file
Image files
Audio files
We also provide an option for users, to upload and download the above files, to a 3rd party cloud storage.
I was wondering, should we use
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
or
FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
for the above file storage purpose?
Historically we used the “Documents” folder, but nowadays the “Application Support” directory is the best place for files like this.
The File System Programming Guide says
Put user data in Documents/. User data generally includes any files you might want to expose to the user—anything you might want the user to create, import, delete or edit. For a drawing app, user data includes any graphic files the user might create. For a text editor, it includes the text files. Video and audio apps may even include files that the user has downloaded to watch or listen to later.
Put app-created support files in the Library/Application support/ directory. In general, this directory includes files that the app uses to run but that should remain hidden from the user. This directory can also include data files, configuration files, templates and modified versions of resources loaded from the app bundle.
Remember that files in Documents/ and Application Support/ are backed up by default. You can exclude files from the backup by calling -[NSURL setResourceValue:forKey:error:] using the NSURLIsExcludedFromBackupKey key. Any file that can be re-created or downloaded must be excluded from the backup. This is particularly important for large media files. If your application downloads video or audio files, make sure they are not included in the backup.
Put temporary data in the tmp/ directory. Temporary data comprises any data that you do not need to persist for an extended period of time. Remember to delete those files when you are done with them so that they do not continue to consume space on the user’s device. The system will periodically purge these files when your app is not running; therefore, you cannot rely on these files persisting after your app terminates.
Put data cache files in the Library/Caches/ directory. Cache data can be used for any data that needs to persist longer than temporary data, but not as long as a support file. Generally speaking, the application does not require cache data to operate properly, but it can use cache data to improve performance. Examples of cache data include (but are not limited to) database cache files and transient, downloadable content. Note that the system may delete the Caches/ directory to free up disk space, so your app must be able to re-create or download these files as needed.
Also see the iOS Storage Best Practices video.
If using the .applicationSupportDirectory, I’d suggest you use url(for:in:appropriateFor:create:) with create set to true:
let folderURL = try! FileManager.default
.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
It doesn't make much difference which you choose. The chief difference is in case you want to use a file browser or the Files app; they can look in your documents directory but not in your application support directory.
Also if you pick one and release the app and later change your mind, it's easy to migrate and change where the app stores its information.
My iOS app is writing to local files to:
/var/mobile/Containers/Data/Application/A.../Library/a.txt
When my app updates, it gets a new application container ID and folder:
/var/mobile/Containers/Data/Application/B...
What happens to all the files I wrote to container ID A?
Is there an "update hook" that will allow me to copy all the "A" container files to path "B"?
Can the new version of the app (B) read the old versions files (A)?
Is there any documentation around what happens to the filesystem during updates?
Is it possible to recover files from container A after B has been installed?
When you update an app, by changing its version number in the .plist file, iOS creates a new directory for that app with a different hexadecimal name and it copies all the files to the new directories. Now if you are using the absolute paths to get the details of files from the directories then those paths would be incorrect and you won't get the file details.
I just tried this in simulator. I created a function as below which will return the document directory path url
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
I called this function from didFinishLaunchingWithOptions in app delegate when version number was 1.0 and it returned the below path :
file:///Users/BhargavRathod/Library/Developer/CoreSimulator/Devices/3082611F-BCCA-4D17-B390-E0EF4CA454DA/data/Containers/Data/Application/72759097-38F3-4292-825E-1D2343219973/Documents/
When I updated the version number to 1.1 it returned me the new path as :
file:///Users/BhargavRathod/Library/Developer/CoreSimulator/Devices/3082611F-BCCA-4D17-B390-E0EF4CA454DA/data/Containers/Data/Application/72DC31E9-C32F-42CC-8449-F1946ADB1018/Documents/
So if you are using a absolute path to access any file from document directory then it is not good practice. You can just save the file name(or relative path after the document directory) and whenever the access to that file name is required then get the file name and append it after the document directory path and access the file.
I hope this will be of some help to you.
My iOS app is writing to local files to: /var/mobile/Containers/Data/Application/A.../Library/a.txt
Okay, stop right there. This is wrong.
Your app has its own sandbox. This sandbox persists forever, thru updates, as long as your app keeps its Bundle ID, and as long as the user does not delete the app.
You thus have no business knowing or thinking about the full absolute path to where your file is. All you know, and all you need to know, is that it is in your app’s sandbox in the Library directory. You can, at any time, obtain the URL of the Library directory by means of its search path:
https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/librarydirectory
And that is where the file will always be. As long as you ask the FileManager for your Library directory and for the a.txt file within it, you will find the same file, regardless of any updates, as long as the user doesn’t actually delete your app (because that deletes the sandbox).
Can explain what happens to the files
Nothing. They stay where they are within the sandbox. The absolute URL of the sandbox may change, but your files are unaffected.
how to keep the files written by the previous version of the app
They are kept automatically. You don’t have to do anything.
(Having said all that, keep in mind that if you submit an app with a different bundle id, that is not a new version of your app. It is a totally different app. In that case you would have a very different problem to solve. This would be no different from any other problem of communicating files from one app to another. You’d need to put the files in a common location, make them available thru the Document Browser, make them exportable by the user, or whatever.)
I'm using a SQLite to store data on my application. To view my data I need access the simulator store and execute the querys. The path to my simulators change every time that I install the app on iOS simulator.
for example a path is:
/Users/augustosansoncadini/Library/Developer/CoreSimulator/Devices/56B6ED1A-8B79-4D5C-836D-D813EEA9FE2F/data/Containers/Data/Application/E7A7BCBD-53FE-4C84-8685-7EA1896694FF/Documents
When I create the SQLite context, I put in this path:
static let fileUrl = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("Database.sqlite3")
So, Database.sqlite3 is stored on the documents folder of application folder. But the name of app change when I reinstall app.
Like I need access often this file, I created a Alias to navigate to this folder, but the Alias not works because the code of the app changes, so I wants to create a database file in the Store of iOS simulator but I don't know what path I must put in this line:
static let fileUrl = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("Database.sqlite3")
By "I reinstall app." you mean that you delete from the simulator device and then install it again? or you mean when you re-run the app?
If it's the second one then you will never find your database since you deleted it along with the app.
I think what you really need is a SQLite editor that can handle file path changes automatically, so you needn't have to worry about what the path actually changes to, right?
If the answer is yes, then give SQLiteFlow a try, it's available on App Store, and from it's documentation, it says:
Handle database file name or directory changes. This makes SQLiteFlow can work friendly with your SQLite database in iOS simulator.
I'm working with SQLite.swift.
In the document, the path to the database is:
let path = NSSearchPathForDirectoriesInDomains(
.DocumentDirectory, .UserDomainMask, true
).first!
but i want to import and use an existing database, so i've dragged my existing database to my keyboard extension folder, and create connection to it with path is:
let path = NSBundle.mainBundle().pathForResource("db", ofType:"sqlite3")
So, i've noticed that the first way, the database will be store in /Users/*/Library/Developer/CoreSimulator/Devices/8B1DB861-AA3F-446F-A559-D4727CDB9285/data/Containers/Data/PluginKitPlugin/0BC647E4-26F3-4A1F-8271-CC73C96FD197/Documents
and the second way, the database will be store in the app.
/Users/*/Library/Developer/CoreSimulator/Devices/8B1DB861-AA3F-446F-A559-D4727CDB9285/data/Containers/Bundle/Application/E5D9514C-859A-4D4D-A771-A8CE9CDCD3E7/AppName.app/PlugIns/AppNameExt.appex
What's different between these two locations?
The second way might increase the app size because it contains the database?
And if i want to Archive/Submit my App to the AppStore with existing database, is this the only way?
The main difference is that storing the file in the documents folder means you can write (update) it, which is pretty important for a database file. You cannot write to a file in the app bundle.
The usual pattern for using a database in an app is:
Create a pre-seeded database during development and copy it to the app bundle during building.
When running, check if the database file exists and is up-to-date in the documents folder.
If not, copy it from the app bundle.
Open the database in the documents folder and read/write as desired.