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.)
Related
I have developed an iOS app that has been downloading files and storing data in the Documents directory. I am storing document’s directory path (where downloaded files get store) in sqlite database. Now if App version get changes then path for database file and document’s directory get changes. If I have manually delete the app and install it again then downloaded files get removed from document’s directory and user has to download files again. Is there any way to get my database file with previously downloaded document’s directory path so that no need to download files again Or any other solution for this?
Understand this concept for document directory
If you update the newer version of the App, Data in the document directory will not getting erased. It will be there. Just the path to reach the document directory get's updated.
So, to overcome the path changing problem. Don't store the entire path to your database file. Just store the ending path or name of the downloaded content to the document directory. Now, if you wants to get some file, lets say example.jpg from the document directory, then you should first get the path to document directory and then append the path of your file.
PATH_TO_DOCUMENT_DIRECTORY/example.jpg this is the complete path for your image. and same is applies for your database.sqlite file.
You can use this handy functions:
func documentsDirPath() -> String {
var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as [String]
return paths[0]
}
And can call it in this way:
let pathToDocumentDirectory = documentsDirPath()
let fileName = "example.jpg" // This you can get from the database.
let filePath = pathToDocumentDirectory + "/\(fileName)"
print(pathToDocumentDirectory)
And for the app that get's deleted, there is no option to recover the contents of the document directory, unless you code and save the data to iCloud and on newer installation of the app, in applicationDidFinishLaunching check if there is some files, present on iCloud with name database.sqlite and other, then you can fetch it and put it to document directory and later you can use.
Hope it helps
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
I am using Cordova fileSystem to download some mp3 Audio files thru my App. I am using cordova.file.cacheDirectory and creating a subfolder within that to store the downloaded files. However, the problem is that each time I make some changes and run the App on iPad I get a different path.
The usual pattern is
file:///var/mobile/Containers/Data/Application/13E9EA83-94A2-4950-811E-E491AC176A78/Library/Caches/MyFolder/MyFiles.mp3
However the long number (App UUID) is not consistent. It changes each time I run the App on iPad through Xcode. Because of this I am unable to access, play, delete any files downloaded during the previous session because I am saving the file names with absolute path in a separate file for quick access in the future.
After some R&D I have realized that even though UUID changes each time, it actually refers to the same location. Hence the solution is not to save absolute path and instead, save only the Path beyond "/MyFolder/" in the above example. Each time when the App is run, the Base Path, which is actually file.cordova.cacheDirectory, should be appended to each entry to obtain the absolute Path to the file.
I found out that the exact URL for the Documents (and other subfolders of my Sandbox) changes when I run my app again. This is inconvenient as I have to rebuild the complete NSURL from the the file name and the current url for the documents subfolder.
Anybody knows the rationale for doing this?
I am working on an app that saves files to the documents directory, and then saves an absolute path for each of those files in an entity using core data. The issue is that each time I rebuild and run my app on my device, the app is saved in a different generated directory, and those file paths are now incorrect. However, my documents directory is still preserved.
I have three questions about this:
If an app is updated on the store, does it then go in a different generated directory, thus invalidating any absolute paths that could be saved in the documents directory?
This is extremely unlikely but is there any way to specify in Xcode to build the app to the same directory the previous build was in?
Is there a way to specify in Xcode that you would like all documents and data wiped with each new build you load on the device?
Thanks everyone!
You said:
"I am working on an app that saves files to the documents directory, and then saves an absolute path for each of those files in an entity using core data."
Don't do that. Ever. The path to your documents directory will be different on different devices, and different if you delete your app and reinstall it. Absolute paths are pretty much guaranteed to fail.
Use paths relative to the sandbox directory in question (documents directory, temp directory, etc)