How to get list of files in iCloud container with swift? - swift

After hours of hard work I could implement iCloud storage to my macOS app.
My container is displayed in iCloud. The name of the folder is correct. I can store generated pdf to all folders, but...
... I can't get a list of files of a certain folder inside this iCloud container.
I use this little snippet of code
let manager = FileManager.default
let driveURL = manager.url(forUbiquityContainerIdentifier: nil)?.appending(path: "Documents").appending(path:"Import")
try? manager.createDirectory(at: driveURL!, withIntermediateDirectories: true, attributes: [:])
let files = manager.enumerator(atPath: driveURL!.absoluteString)
files ist always empty (nil), because the folder Import doesn't exist (what's wrong, because it's there). And it should be created, if not exists.
Do I miss some settings to my project, to get access to my own folders? Or is there another, different way to get reading access?

Related

Is there a way to work with FileManager and NSBundle to get all the applications that support a given type of file in the /Applications directory?

I'm creating a Commandline tool that will get an input from a user to search for a specific application that supports a certain file extension. For example, if I enter mp4, it will probably show me QuickTime. I'm looking for the specific FileManager manipulation to achieve this in Swift.
I think you are looking for NSWorkspace.urlForApplication(toOpen:). It finds the application that would be opened if you had double clicked on a file, and returns its URL. Since it requires a file to work, you need to first create a temporary empty file somewhere, with the desired extension, then call this method.
let tempFileURL = FileManager.default.temporaryDirectory.appendingPathComponent("foo.mp4")
FileManager.default.createFile(atPath: tempFileURL.path, contents: nil, attributes: nil)
// this gives me the URL for QuickTime Player:
// file:///System/Applications/QuickTime%20Player.app/
let url = NSWorkspace.shared.urlForApplication(toOpen: tempFileURL)

Swift: How to unzip file not contained in my bundle?

I am not very familiar with Swift programming but I need to write a small tool in Swift which can unzip a file (and then launch a program). I need to unzip a file which is not contained in my app bundle. It is located in /Users/me/folder1/folder2/openjdk-11.0.2.zip
I tried the libraries "Zip", "ZipFoundation", and "SSZipArchive". From what I read so far, I think that the libraries which I tried need the zip file to be located in the app bundle but I am not sure.
With "Zip" I tried:
_ = try Zip.quickUnzipFile(URL(string: openjdkZipUrl!.relativePath)!)
With "ZipFoundation" I tried:
let fileManager = FileManager()
let archive = openjdkZipUrl
let destinationURL = openjdkFolderUrl
do {
try fileManager.unzipItem(at: archive.url, to: destinationURL)
} catch {
}
ZipFoundation told me "Value of type 'FileManager' has no member 'unzipItem'" but I imported it with import Foundation. I also have it (and the other libraries) in my Podfile.
With "SSZipArchive" I tried:
let success = SSZipArchive.unzipFile(atPath: openjdkZipUrl!.path, toDestination: openjdkFolderUrl!.path)
The used paths are
let openjdkZip = "file:///Users/" + user + "/folder1/folder2/openjdk-11.0.2.zip"
let openjdkZipUrl = URL(string: openjdkZip)
and
let openjdkFolder = "file:///Users/" + user + "/folder1/folder2/openjdk-11.0.2"
let openjdkFolderUrl = URL(string: openjdkFolder)
Is it really a problem that the zip file is not contained in my bundle? Can someone tell me what I did wrong?
Thanks in advance
#trojanfoe mentioned in the comments:
Mac apps are sandboxed by default which means they have no access to a user's files unless they ask for it by getting the user to open the file/folder. You should ensure it's turned off for your app, however you are testing if the file exists and if this is succeeding then it looks like sandboxing is not turned on?
I looked at the .entitlements file in my project and found out that "App Sandbox" was set to "YES". I set it to "NO" and it worked perfectly.
It seems that you can check for a file while in sandbox mode (as I did with my condition) but not access them when trying to unzip them.
Thanks again #trojanfoe :)

Xcode Project Folder Structure

I am using the latest XCode / Swift 3.0 and facing some problems:
I created a folder in /MyProject/MyProject/Assets/Subfolder1 and stored a few hundred .txt files in it to iterate over the files inside the Subfolder1 with the following code:
let fm = FileManager.default
fm.enumerator(atPath: "/MyProject/Assets/Subfolder1")?.forEach({ (e) in
if let e = e as? String, let url = URL(string: e) {
doSomethingWith(url.pathExtension)
}
})
But I cannot find any files. I tried some variations ("/Assets/Subfolder1/" and "/MyProject/MyProject/Assets/Subfolder1"), all are not working.
What is the correct path that I have to specify?
Best
Chris
First off, make sure you have added the actual folder to the Xcode project. You can do this simply by dragging and dropping the folder into your project. After you drag and drop, this window should appear
Make sure you select Create folder references and Copy items if needed. This will make sure that the entire folder is constantly synced inside your Xcode project. Then to verify that the assets will be transferred to your device when building the project, go into Build Phases and then to Copy Bundle Resources and you should see the name of the folder, in my case, I have named it TextFiles.
Now because you have added your folder into the application's Main Bundle, you can access it by doing this:
let fm = FileManager.default
let path = Bundle.main.resourcePath?.appending("/TextFiles")
fm.enumerator(atPath: path!)?.forEach({ (e) in
if let e = e as? String, let url = URL(string: e) {
doSomethingWith(url.pathExtension)
}
})
The reason we need to do the Bundle.main.resourcePath before it and can't simply say /TextFiles is because if we say /TextFiles it looks for that folder starting from the system root, which is why it wasn't working before. It would be like having a folder in C:/Users/Abc123/Documents/TextFiles but the system is looking for it in C:/TextFiles.

Get number of images in xcasset

I want to programmatically load a couple of images into arrays from my xcassets. I don't know how many images there are in the asset, but the images are named in order, like this: "img1_1", "img1_2", "img2_1", "img2_2", ...
I put the images in folders inside the asset, so folder "images1" contains all images with names starting with "img1_" and the folder called "images2" contains all images starting with "img2_". Does that help?
How do I get the number of images in the asset that are named like that so I can iterate through them and add them to my array?
There isn't a real easy way to go about it since the files are placed in the app at compile time. You can, though, create a RunScript in the Build Phases to be ran before compiling that creates a text file of the images. Then you can read in that text file and populate an array of images. You can use that array to get the details you need.
RunScript in the Build Phases:
#!/bin/sh
>./your_app_folder/fileNames.txt
for FILE in ./your_app_folder/Images.xcassets/actions/*; do
echo $FILE >> ./your_app_folder/fileNames.txt
done
Also, here's a link to an accepted answer that a previous poster asked with more details.
Another option if you do not want to deal with Build Phases, and one I'd probably choose, is not to use the Assets.xcassets file. Just place the images in a folder within your app bundle. It's much easier to read from the bundle.
UPDATE:
For the second option, you can drag your images (or folder of images) to your project, but be sure copy as a folder reference rather than group. Then in your code, you can read that folder using the FileManager.
let fileManager = FileManager.default
let imagePath = Bundle.main.resourcePath! + "/your_new_folder"
let imageNames = try! fileManager.contentsOfDirectory(atPath: imagePath)
imageNames in this case will be an array of file names within that url path. If go this route, you probably have to load the images by contentsOfFile too.
if let imagePath = bundle.path(forResource: fileName, ofType: nil) {
myImage = UIImage(contentsOfFile: imagePath)
}

Swift - Listing contents of a non-local directory

I'd like to list the contents of an external directory in Swift 2. It seems easy enough for a local directory, but I just can't figure it out with an external directory. Here is my code:
var theUrlString = "https://great-castles.com/images/berkeley/"
var theUrl = NSURL(string: theUrlString)!
do {
let directoryContents = try NSFileManager.defaultManager().contentsOfDirectoryAtURL(theUrl, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions())
print(directoryContents)
} catch let error as NSError {
print(error.localizedDescription)
}
In the playground, I am getting the error:
The file “berkeley” couldn’t be opened because there is no such file
Note that I just threw a random URL in there as an example. But it is accessible, so I should be able to get a list of the files, right? Does NSFileManager.defaultManager think I am referring to a local file?
What I'd really like to do is copy the contents of an online directory into the document directory on the device. If the above isn't possible, any ideas on the best way to do that?