I have a folder (untagged-data) in Xcode that consists of a lot of images (100). I am trying to load the images into my application but for some reason the path is not correct and I am not able to load. Here is the URL I get which I am trying to load.
file:///Users/johndoe/Library/Developer/CoreSimulator/Devices/66763907-9153-443A-BA0E-D5CB6CC9280C/data/Containers/Bundle/Application/D3C77C63-CA3D-4238-8EAD-97B1DA15F2C6/MyApp.app/untagged-data/vessey.jpg
Here is the code which populates an array with the paths:
guard let resourceURL = Bundle.main.resourceURL else {
fatalError("Bundle not found")
}
let resourcePath = resourceURL.appendingPathComponent("untagged-data")
let paths = try! FileManager.default.contentsOfDirectory(at: resourcePath, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
for resourceURL in paths {
let path = resourceURL.absoluteString
self.images.append(path)
print(path)
}
When I try to create an image it simply throws an exception:
//let img = UIImage(named: images[index])
let img = UIImage(contentsOfFile: images[index])
Open the path below path in safari to check whether path exists or not
file:///Users/johndoe/Library/Developer/CoreSimulator/Devices/66763907-9153-443A-BA0E-D5CB6CC9280C/data/Containers/Bundle/Application/D3C77C63-CA3D-4238-8EAD-97B1DA15F2C6/MyApp.app/vessey.jpg
If path exists then comment the below line in code
//let resourcePath = resourceURL.appendingPathComponent("untagged-data")
Related
I've copied a folder into the documents directory, and I'm able to enumerate the directory's contents, but when I check if the enumerated URL exists and is readable, I get false. How do I read and use these files?
let imagesURL = copyPath.appendingPathComponent("images", isDirectory: true)
guard let fileEnumerator = FileManager.default.enumerator(at: imagesURL, includingPropertiesForKeys: nil, options: FileManager.DirectoryEnumerationOptions()) else { return }
while let file = fileEnumerator.nextObject() {
guard let filepath = file as? NSURL else { continue }
print(filepath.absoluteString!)
let isReadable = FileManager.default.isReadableFile(atPath: filepath.absoluteString!)
let exists = FileManager.default.fileExists(atPath: filepath.absoluteString!)
print("isReadable: \(isReadable), exists: \(exists)")
}
absoluteString is the wrong API. You have to get paths in the file system with the path property.
And for consistency please name the URL as fileURL
...
guard let fileURL = file as? URL else { continue }
print(fileURL.path)
let isReadable = FileManager.default.isReadableFile(atPath: fileURL.path)
let exists = FileManager.default.fileExists(atPath: fileURL.path)
...
When I run this code and add a breakpoint:
var pathFor = Bundle.main.path(forResource: imageName, ofType: "png")
print("breakpoint added here")
I see a nil value for the pathFor variable.
However, if I contextually check the file existence in my app Bundle (using XCode -> Device -> Device Name -> Download Container -> Show package content), I can see it inside the Documents directory:
What am I doing wrong?
UPDATE:
I have modified the code, following the suggestion in the answer.
Unfortunately I am unable to instantiate an image based on the path.
Please see here:
You are looking inside the Bundle ( i.e.: files embed on compilation time ) for a file you put in the Documents Folder. that ain't gonna work.
Your file is here :
if let dir = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.allDomainsMask, true).first {
if let path = NSURL(fileURLWithPath: dir).appendingPathComponent("file.html") {
print(path as Any)
if let imageData = NSData(contentsOf: path!) {
let image = UIImage(data:imageData as Data)
}
}
Another permutation, but I'd personally do:
let fileURL = try! FileManager.default
.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent(imageName)
.appendingPathExtension("png")
let image = UIImage(contentsOfFile: fileURL.path)
Alright, Im fairly new to the url locating process (I always just use explicit names) and everyone is new to MSMessageStickers. However. I need to pull in an array of image urls to use as MSStickers from a folder of images I have copied into my MessagesExtension target in my project here (it is starterPack):
It may the Swift 3 syntax screwing this up or something else, but I CANT find any way to just get the right url of this folder and get all the images inside of it. The following is successful in making stickers out of PNGS with specific names:
for i in (1..<2) {
if let url = Bundle.main.url(forResource: "test\(i)", withExtension: "png") {
do {
//let sticker = try MSSticker(contentsOfFileURL: url, localizedDescription: "")
let sticker = try MSSticker(contentsOfFileURL: url, localizedDescription: "")
//print("SUCCESS", url)
stickers.append(sticker)
} catch {
print(error)
}
}
}
And I have adapted the following to Swift 3 from similar question How to get array of UIImage, from folder, in Swift? :
if let path = NSBundle.mainBundle().resourcePath {
let imagePath = path + "/images"
let url = NSURL(fileURLWithPath: imagePath)
let fileManager = NSFileManager.defaultManager()
let properties = [NSURLLocalizedNameKey,
NSURLCreationDateKey, NSURLLocalizedTypeDescriptionKey]
do {
let imageURLs = try fileManager.contentsOfDirectoryAtURL(url, includingPropertiesForKeys: properties, options:NSDirectoryEnumerationOptions.SkipsHiddenFiles)
print("image URLs: \(imageURLs)")
// Create image from URL
var myImage = UIImage(data: NSData(contentsOfURL: imageURLs[0])!)
} catch let error1 as NSError {
print(error1.description)
}
}
But because the folder is not technically in my project folder but rather in the messagesExtension folder as you can see, I think that is why it cant find it.
I need to bring in and get the url of all the images contained in my stickers folder. What am I doing wrong?
I'm trying to use Swift to iterate over the images I have put into my Assets folder. I'd like to iterate over them and insert them into a .nib file later, but so far I cannot find how to get something like:
let assetArray = ["image1.gif", "image2.gif", ...]
Is this possible? I've been playing with NSBundle.mainBundle() but couldn't find anything on this. Please let me know. Thanks!
Assets.xcassets is not a folder but an archive containing all the images using Assets.car as its filename.
If you really want to read the assets file then you need to use some library that can extract the contents of the file like this one.
Or you can create a bundle in your project and drag all the images you have there. In my case, I have Images.bundle in my project. To get the filenames you can do the following:
let fileManager = NSFileManager.defaultManager()
let bundleURL = NSBundle.mainBundle().bundleURL
let assetURL = bundleURL.URLByAppendingPathComponent("Images.bundle")
let contents = try! fileManager.contentsOfDirectoryAtURL(assetURL, includingPropertiesForKeys: [NSURLNameKey, NSURLIsDirectoryKey], options: .SkipsHiddenFiles)
for item in contents
{
print(item.lastPathComponent)
}
SWIFT 3/4 Version:
let fileManager = FileManager.default
let bundleURL = Bundle.main.bundleURL
let assetURL = bundleURL.appendingPathComponent("Images.bundle")
do {
let contents = try fileManager.contentsOfDirectory(at: assetURL, includingPropertiesForKeys: [URLResourceKey.nameKey, URLResourceKey.isDirectoryKey], options: .skipsHiddenFiles)
for item in contents
{
print(item.lastPathComponent)
}
}
catch let error as NSError {
print(error)
}
I have an ordinary Xcode project like this ...
notice there's a folder (it is an actual folder - not just a group) named "images". It contains 25 ".png" images.
All I want to do is make an array of UIimage with each of those images.
(Or even, an array of the image names or similar, that would be fine - then could load them UIImage(named:)
How do I get at that folder "images"?? What about a subfolder "images/cars"?
I tried something like this but it finds nothing...
override func viewDidLoad()
{
let imageArray = NSBundle.mainBundle().URLsForResourcesWithExtension(
"png", subdirectory: "images")
print("test...")
for n:NSURL in imageArray!
{ print("found ..." ,n) }
}
We we assume the images are in the app's resource bundle. If not you need to make sure that your images directory is listed in the "Copy Bundle Resources" in the "Build Phases" of the target.
EDIT
This is only going copy the images into the app bundle, if you require the folder to be copied to the app bundle per the code below then please use the follow StackOverflow question to set it up correctly.
This gives us an array of URL's that we can then use with UIImage(data:) and NSData(contentsOfURL:) to create the image when needed.
Get the bundle's resource path and append the image directory then get the contents of the directory.
if let path = NSBundle.mainBundle().resourcePath {
let imagePath = path + "/images"
let url = NSURL(fileURLWithPath: imagePath)
let fileManager = NSFileManager.defaultManager()
let properties = [NSURLLocalizedNameKey,
NSURLCreationDateKey, NSURLLocalizedTypeDescriptionKey]
do {
let imageURLs = try fileManager.contentsOfDirectoryAtURL(url, includingPropertiesForKeys: properties, options:NSDirectoryEnumerationOptions.SkipsHiddenFiles)
print("image URLs: \(imageURLs)")
// Create image from URL
var myImage = UIImage(data: NSData(contentsOfURL: imageURLs[0])!)
} catch let error1 as NSError {
print(error1.description)
}
}
You can follow these steps to download them:
Create a new folder in finder and add all images (or folder, ...
everything).
Change folder name + ".bundle" (for example: YourListImage ->
YourListImage.bundle).
Add folder to project.
Add FileManager extension:
extension FileManager {
func getListFileNameInBundle(bundlePath: String) -> [String] {
let fileManager = FileManager.default
let bundleURL = Bundle.main.bundleURL
let assetURL = bundleURL.appendingPathComponent(bundlePath)
do {
let contents = try fileManager.contentsOfDirectory(at: assetURL, includingPropertiesForKeys: [URLResourceKey.nameKey, URLResourceKey.isDirectoryKey], options: .skipsHiddenFiles)
return contents.map{$0.lastPathComponent}
}
catch {
return []
}
}
func getImageInBundle(bundlePath: String) -> UIImage? {
let bundleURL = Bundle.main.bundleURL
let assetURL = bundleURL.appendingPathComponent(bundlePath)
return UIImage.init(contentsOfFile: assetURL.relativePath)
}
}
Use:
let fm = FileManager.default
let listImageName = fm.getListFileNameInBundle(bundlePath: "YourListImage.bundle")
for imgName in listImageName {
let image = fm.getImageInBundle(bundlePath: "YourListImage.bundle/\(imgName)")
}
Please try the following:
You have to register your images to "Copy Bundle Resources".
You have to add filter module in main Bundle.
enter image description here
It is working well on my side. Maybe you can change filter from "jpg" format into "png" one.
I've tested on iOS 10.x later, Swift 3.0 and xcode 8.1 version.
I would advise against loading all of your images into an array at once. Images tend to be large and it's easy to run out of memory and crash.
Unless you absolutely have to have all the images in memory at once it's better to keep an array of paths or URLs and load the images one at a time as needed.
Assuming the folder full of images is in your app bundle, you can use the NSBundle method URLsForResourcesWithExtension:subdirectory: to get an array of NSURLs to all the files in your images subdirectory, either with a specific filetype, or ALL files (if you pass nil for the extension.)
Once you have an array of file urls you can map it to an array of paths if needed, and then map that to an array of images.
Swift 4
if let path = Bundle.main.resourcePath {
let imagePath = path + "/images"
let url = NSURL(fileURLWithPath: imagePath)
let fileManager = FileManager.default
let properties = [URLResourceKey.localizedNameKey,
URLResourceKey.creationDateKey,
URLResourceKey.localizedTypeDescriptionKey]
do {
let imageURLs = try fileManager.contentsOfDirectory(at: url as URL, includingPropertiesForKeys: properties, options:FileManager.DirectoryEnumerationOptions.skipsHiddenFiles)
print("image URLs: \(imageURLs)")
// Create image from URL
let firstImageURL = imageURLs[0]
let firstImageData = try Data(contentsOf: firstImageURL)
let firstImage = UIImage(data: firstImageData)
// Do something with first image
} catch let error as NSError {
print(error.description)
}
}