I would like to get the subfolders structure in the Resources folder of a Swift Playground.
I've tried using this approach with no luck
let docsPath = Bundle.main.resourcePath! + "/Resources"
let directoryContents = try? fileManager.contentsOfDirectory(atPath: docsPath)
This results in nil and I can't get the tree structure of the folders, is this possible?
Solved it!
let docsPath = Bundle.main.resourcePath!
let urls = Bundle.main.urls(forResourcesWithExtension: nil, subdirectory: "dataset/train")
I would recommend to allow NSBundle to find your resources exactly where they are, so instead of
let docsPath = Bundle.main.resourcePath! + "/Resources"
you can use somewhere inside your class (moreover, such class will be transferable to real project)
let docsPath = Bundle(for: type(of: self)).path(forResource: "dataset", ofType: nil)
and you get exact path.
Btw, it can be something like
/var/folders/gs/hkhcv3rx5wd5lqrfvh1ll6g40000gn/T/com.apple.dt.Xcode.pg/resources/620432D5-9F12-4FC8-B271-17153FC9D797/dataset
that is why it's better to avoid hardcoding.
Related
I appreciate some assistance. I created a folder inside my documents directory named "MyPhotos". I added three image files to the folder. No issues.
Next I'm attempting to construct some code that will delete the files when needed but can't get it right. I can append the MyPhotos folder to the search path but can't subsequently append the file name to the path after multiple tries. tempPhotoTitle is a variable. Thank you for helping.
let fileManager = FileManager.default
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,true)[0] as NSString
let destinationPath = documentsPath.appendingPathComponent("MyPhotos")
let finalPath = destinationPath.appending(tempPhotoTitle)
do {
try fileManager.removeItem(atPath: finalPath)
}
catch {
print(error)
}
The issue there is that you are working with strings (paths) and not adding the slash. I recommend always working with URLs this way you dont need to worry about adding the slash to your path.
do {
let tempPhotoTitle = "filename.jpg"
let documents = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let photos = documents.appendingPathComponent("MyPhotos")
let fileURL = photos.appendingPathComponent(tempPhotoTitle)
try FileManager.default.removeItem(at: fileURL)
} catch {
print(error)
}
Leo Dabus's answer of working with URLs is the better one. However, it's worth mentioning that when working with Strings, if you bridge to NSString again, appendingPathComponent is available:
let finalPath = (destinationPath as NSString).appendingPathComponent(tempPhotoTitle)
I have json file that I want to include in the test bundle so I can just read this json for my tests.
So I created a file called "test.json", it is in my Tests folder.
Now I want to read this file. I am reading it like this, the code here is in the test file in test bundle:
let bundle = Bundle(for: type(of: self))
var url = bundle.url(forResource: "test", withExtension: "json")
the url is nil every single time. I swear that file is there, if I open it in finder, it's under the same directory as the test-info.plist. I even tried the main bundle but it is still nil!!
Where is this file????
Try this:
let bundle = Bundle(for: YourTestClass.self)
let path = bundle.path(forResource: "test", ofType: "json")
let data = try Data(contentsOf: URL(fileURLWithPath: path))
I'm updating my app with the new iOS 11 standards and a lot of stuff were deprecated and now I'm stacked with this error: "Argument labels '(contentsOfFile:)' do not match any available overloads.
Here you are the codes that was working:
//load plist file
var palermoip: NSArray?
if let path = Bundle.main.path(forResource: "palermoip", ofType: "plist") {
palermoip = NSArray(contentsOfFile: path)
}
Anyone knows how can I fix it? Thank you in advance !
I recommend to use PropertyListSerialization and the URL related API
let url = Bundle.main.url(forResource: "palermoip", withExtension: "plist")!
let data = try! Data(contentsOf:url)
let palermoip = try! PropertyListSerialization.propertyList(from: data, format: nil) as! [[String:Any]] // or [Any] if the array does not contain dictionaries
and in Swift 4 even PropertyListDecoder
I have a file stored in:
/var/mobile/Containers/Data/Application/083EA15E7/Documents/myFile.zip
It got there after I downloaded it from a server.
If I know the file name is myFile.zip, how can I find it with NSBundle?
Like this:
if let URL = NSBundle.mainBundle().URLForResource("myFile", withExtension: "zip") {
// do stuff
}
currently this returns false, not sure how I can specify the whole path. Any ideas?
This item is not in your bundle, an item in your bundle is something that you add before compiling, such as assets, fonts etc.
iOS provides each app with a sandbox. In that sandbox, the Documents folder exists. To access files from the Documents folder try this:
let documentsURL = NSURL(
fileURLWithPath: NSSearchPathForDirectoriesInDomains(
.DocumentDirectory, .UserDomainMask, true).first!,
isDirectory: true
)
To get the file, you will need to get its path and append it to the documents path like so.
let URLToMyFile = documentsURL.URLByAppendingPathComponent("MyFile.zip")
To get the path as a string you can access the path property of the URL.
print(URLToMyPath.path!)
That will print out the path of your downloaded resource.
Tested on: xCode 8.3.2 & Swift 3.1
First drag your file (JPG, MP3, ZIP) inside your project folder and make sure Copy items if needed is checked and project/app is selected in Add to targets
Inside relevant ViewController
let fileName = "fileName"
let fileType = "fileType"
if let filePath = Bundle.main.path(forResource: fileName, ofType: fileType) {
print(filePath)
}
If you need to get the file URL you can use NSBundle method
if let fileURL = Bundle.main.url(forResource: fileName, withExtension: fileType) {
print(fileURL)
}
Also NSBundle method pathForResource has an initializer that you can specify in which directory your files are located like:
if let filePath = Bundle.main.path(forResource: fileName, ofType: fileType, inDirectory: "filesSubDirectory") {
print(filePath)
}
And for getting file URL:
if let fileURL = Bundle.main.url(forResource: fileName, withExtension: fileType, subdirectory: "filesSubDirectory") {
print(fileURL)
}
run time created file are stored in Document directory not in NSBundle. NSBundle stores the files like System file you put in your Xcode project while your developing
Here is the example
This code is fully tested on Swift 2.0
let file = "myFile.zip"
if let dir : NSString = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first {
//path will be stored here
let sPath = dir.stringByAppendingPathComponent(file);
print(sPath) // printing the file path
}
I'm trying to load an image from an iOS 8 framework that I'm writing (in Swift). I'm using Xcode 6 Beta 6
This code does not work (i.e. load image) if the image is stored in my framework's Images.xcassets:
let image = UIImage(named: "Background.png")
If the image is stored in an Images.xcassets of a host application (that uses the framework), then the image is loaded properly (from code inside the framework).
I can see that the framework's Images.xcassets is included in the Copy Bundle Resources phase.
I'm also using a storyboard file as a resource in the framework; and this loads properly.
I've tried renaming the Images.xcassets of the framework to avoid some kind of naming collision with the host application, but this doesn't work either.
While #Renatus answer is perfectly valid and addresses the core issue (bundle for framework needs to be specified), I wanted to post the solution I went with since it's slightly more direct:
Swift 3.0/4.0/5.0
let image = UIImage(named: "YourImage", in: Bundle(for: YOURFRAMEWORKCLASS.self), compatibleWith: nil)
Alternatively, you can use this pattern for non-class, aka non-"static", functions:
let image = UIImage(named: "YourImage", in: Bundle(for: type(of: self)), compatibleWith: nil)
or this pattern for class functions:
let image = UIImage(named: "YourImage", in: Bundle(for: self), compatibleWith: nil)
These alternatives are better for cutting and pasting.
UIImage(named: "Background.png") calls NSBundle.mainBundle() in the internals. So, your code is trying to find resource in your host app's bundle, not in the frameworks bundle. To load UIImage from your framework's bundle use this snippet:
let frameworkBundle = NSBundle(forClass: YOURFRAMEWORKCLASS.self)
let imagePath = frameworkBundle.pathForResource("yourImage.png", ofType: "")
if imagePath != nil {
result = UIImage(contentsOfFile: imagePath!)
}
Edited: added explanation (thx to milz)
In Swift 3.0:
let currentBundle = Bundle(for: YOURCLASS.self)
guard let path = currentBundle.path(forResource: imageName, ofType: "jpg") else { return defaultImage }
return UIImage(contentsOfFile: path) ?? defaultImage
Another option is assigning the bundle identifier, which makes more sense than assigning class when it comes to readability.
In Swift 3:
UIImage(named: "MyImage", in: Bundle(identifier: "bundleIdentifier"), compatibleWith: nil)
The accepted answer didn't work for me. Here's a fool proof way for loading an image embedded in a dynamic framework:
var bundle = NSBundle(forClass: self.classForCoder)
if let bundlePath = NSBundle(forClass: self.classForCoder).resourcePath?.stringByAppendingString("/MYLIB.bundle"), resourceBundle = NSBundle(path: bundlePath) {
bundle = resourceBundle
}
let image = UIImage(named: "my-embedded-image", inBundle: bundle, compatibleWithTraitCollection: nil)