Why is there a mismatch between FileManager and Finder? - ios

If I print the document directory when the simulator starts, I get this:
let simulatorPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
print(simulatorPath)
//prints -> /Users/name/Library/Developer/CoreSimulator/Devices/[device-id]/data/Containers/Data/Application/[application-id]/Documents
If I open this directory with Finder, there are a few other folders there: /Library, /SystemData, and /tmp. Specifically, /Library/Caches/[domain.app]/[several cache files].
However, in my app, I'm creating a sqlite database using the file manager. And if I do the following after creating the database:
var path = FileManager.default.currentDirectoryPath + "Library/Caches"
let enumerator = FileManager.default.enumerator(atPath: path)
while let obj = enumerator?.nextObject() as? String {
print(obj)
}
This is printed:
ColorSync
ColorSync/com.apple.colorsync.devices
Desktop Pictures
Desktop Pictures/78DJQ81B-3D2C-46C7-A268-3CE1903213FE
Desktop Pictures/78DJQ81B-3D2C-46C7-A268-3CE1903213FE/lockscreen.png
domain.app
domain.app/SQLite
com.apple.cloudkit
com.apple.cloudkit/com.apple.cloudkit.launchservices.hostnames.plist
com.apple.iconservices.store
app
app/SQLite
app/SQLite/cache.db
But the contents of the /Library/Caches/[domain.app] folders are different when printed with the enumerator, vs visited in Finder. Am I wrong in assuming that
NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
and
FileManager.default.currentDirectoryPath + "/Documents"
point to the same location?

After stumbling around Finder for a while, I discovered the SQLite db file I was creating was showing up in /Library/Caches, but in my hard drive's root directory. According to docs for FileManager.default.currentDirectoryPath:
When an app is launched, this property is initially set to the app’s current working directory. If the current working directory is not accessible for any reason, the value of this property is nil.
Given this, I figured when I printed that value, and / came out, it was relatively referring to the simulated app's current directory. If anyone knows why this is the case, comments welcome.

Related

Get Reference to SceneKit Catalog Swift

I must be missing something simple - I'm trying to iterate through the
files in an .scnassets folder but can't seem to get a reference to the
folder/catalog.
Here's the organizer:
Models.scnassets contains one file. I tried this:
let fileManager = FileManager.default
let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
let docsURL = urls.first
let assetFolderPath = docsURL?.appendingPathComponent("Models.scnassets").path
And I tried this and several other variants:
let modelPathString = "ARAds/Models.scnassets"
Then I attempted to count the files with both of the above paths:
do {
let modelPathDirectoryFiles = try fileManager.contentsOfDirectory(atPath: assetFolderPath!)
//or modelPathString
print(modelPathDirectoryFiles.count)
} catch {
print("error getting list of files")
}
I get the error message in all cases.
I assume there must be some special way to get a reference to a SceneKit
Catalog but I have not been able to find that in the Apple docs nor SO.
Any guidance would be appreciated. iOS 11.4 Xcode 10.0
Looking at your code, the first thing I see, is that you are referencing the Documents Directory which isn't actually where your folder is.
The Documents Directory is a folder on your actual device where you might save user data or other files which can be accessed at a latter date (for example via iTunes Sharing).
If you move your Models.scnassets folder under the yellow ArAds folder you should be able to access your content like so:
let myModelToLocate = SCNScene(named: "Models.scnassets/Phone_01.scn")
Hope it helps...
You've pointed me in a better direction, but I can already get the scn and make a node if I know the name. What I really want to do is populate a tableview with the options that are available - so I need to find the current list of scene files.
I think this will work:
let subdir = Bundle.main.resourceURL!.appendingPathComponent("Models.scnassets").path
do {
let modelPathDirectoryFiles = try fileManager.contentsOfDirectory(atPath: subdir)
print(modelPathDirectoryFiles.count) //this works
//then do my thing with the array
} catch {
print("error getting list of files")
}
This seems to work, whether I move the folder or not.

iOS10 + Xcode8 documentDirectory weird behavior

It seems the documentDirectory in Xcode8/Swift3/iOS10, in a framework, on iOS seems unwritable.
API's used / tried:
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
( The last one does not seem to be preferred in Swift, which I can understand )
Now, whenever I try to write files to the URL returned in this area I do not seem to be capable of doing so ( both Simulator, and device ). Downloading the container or inspecting it does not show the files either ( I tried several methods of writing ). Also trying to create a directory to write into seems to fail.
The weird thing is that there is no error returned from within API's used or the FileManager itself.
Is there some horrible point I'm missing? Is it a bug I should report? Currently I moved to creating a directory in Library/ instead, as that seems to work and shouldn't be as volatile as Library/Cache/.
Code used to write ( realm.io was used before I decided to do this ):
let URLs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let data = Data.random(32) // Generates a 32 byte long random blob
try! data.write(to: URLs.last!) // Crashing here with a forced unwrap is fine
The path that you are writing to is invalid – you're passing in the directory path instead of the path to the file you want to create. You can craft a path like this:
let path = NSString(string: URLs.last!.path).appendingPathComponent("foo.txt")
Turns out you need to completely reset your Simulators and restart Xcode. Fun stuff.

Where is the Core Data file located?

I use Core Data in my application, and I want to know that where is the SQLite file located.
I have already read the relative post and I didn't find the answer.
During initialization of the Core Data Stack you decide, where the database file will be located. The standard place is the documents directory. See Apple Developer - Initializing the Core Data Stack.
You will find there the following code
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let docURL = urls[urls.endIndex-1]
/* The directory the application uses to store the Core Data store file.
This code uses a file named "DataModel.sqlite" in the application's documents directory.
*/
let storeURL = docURL.URLByAppendingPathComponent("DataModel.sqlite")
The storeURL is the file URL you are looking for (and docURL is just a directory without a file name included).
You can also find this directory using NSSearchPathForDirectoriesInDomains
NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).last! as String
Check IOS 8 Store sqlite File Location Core Data for other ideas like find used in Terminal for example.

Application ID of NSSearchPathForDirectoriesInDomains Changes per Simulator Run & Update App on Real Device

I'd like to persist images to user domain of iPhone so I write the following code.
let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0]
print(path)
It shows like: /Users/xxx/Library/Developer/CoreSimulator/Devices/1312F880-6BDC-45D2-B3B3-4D2374313C67/data/Containers/Data/Application/A2850237-5E71-4373-81A6-B443032E1951/Documents/
In this case, Application ID is A2850237-5E71-4373-81A6-B443032E1951
And the problem is when I run on simulator again WITHOUT REMOVING THE APP, it shows like: /Users/xxx/Library/Developer/CoreSimulator/Devices/1312F880-6BDC-45D2-B3B3-4D2374313C67/data/Containers/Data/Application/1F9B5B0A-5A6C-4098-BF40-C978C60C93AF/Documents/
In this case, Application ID is 1F9B5B0A-5A6C-4098-BF40-C978C60C93AF
So there are Application ID difference between previous and current install although I just did update the app and didn't remove the app. Why it is caused and how to fix it?
It causes Xcode 7.2, 7.1, 7.0. And it causes with not only simulator install but also actual device install. So if iOS users update the app from app store, the Application ID will be changed and app sandbox will also be changed and finally users cannot refer their images.
Similar Situations:
Xcode 6.3 seems to change the path to the Documents directory per app run
xcode 6.2 create a new simulator path every time when run the app
Related Guidelines:
File System Basics
Thanks in advance.
EDIT
It seems I have to persist path as relative not absolute.
Application folder name changes every time i run in simulator [duplicate]
Xcode 6 keeps renaming my app's directory in iOS8 simulator after each run.
I'll try the approach and if I solved my problem, I'll update the question.
I have to persist path relative not absolute. And I also can salvage old run images by fetching with NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] + "persisted relative path".
A better solution is to save a bookmark data
https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/AccessingFilesandDirectories/AccessingFilesandDirectories.html
A bookmark is an opaque data structure, enclosed in an NSData object,
that describes the location of a file. Whereas path- and file
reference URLs are potentially fragile between launches of your app, a
bookmark can usually be used to re-create a URL to a file even in
cases where the file was moved or renamed
First you must use NSURL instead of String
Convert an NSURL to NSData
let data: NSData? = try? url.bookmarkDataWithOptions(.SuitableForBookmarkFile, includingResourceValuesForKeys: nil, relativeToURL: nil)
Read an NSURL from bookmark NSData
var isStale: ObjCBool = false
let url = try? NSURL(
byResolvingBookmarkData: bookData,
options: [],
relativeToURL: nil,
bookmarkDataIsStale: &isStale)
guard let fullURL = url else {
return nil
}
You can fill relativeToURL to your document directory url
Alternatively you can use FileKit : path.bookmarkData and Path(bookmarkData: ..)
try to persist your file just with the name.extension
to save document
let pathDocument = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0]
let fullPath = let fullPath = pathDocument+"/"+"fileName.ext"
//...add some code to save document at `fullPath`...
to get document
let pathDocument = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0]
let fullPath = let fullPath = pathDocument+"/"+"fileName.ext"
//... add code to get data at path : `fullPath`....

Valid file path for archiverootobject and unarchiverootobject

I am making an iPhone app and in a previous question I was told that I needed a valid file path for archiverootobject and unarchiverootobject but I don't know how to make one. So what is a valid file path to save arrays of custom classes?
Follow up question: On the linked question I have set up my methods to use invalid saves but it still works would anyone know why?
You can save it to a subdirectory folder named with your bundleID inside the application support folder or you can also save it to the preferences folder located inside the library directory:
let preferencesDirectoryURL = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!.appendingPathComponent("Preferences", isDirectory: true)
let fileURL = preferencesDirectoryURL.appendingPathComponent("fileName.plist")
print(fileURL.path) // "/var/folders/.../Library/Preferences/fileName.plist

Resources