Asset Catalog: Access Images with Same Name in Different Folders

Asset Catalog: Access images with same name in different folders

Click on each folder in the assets catalog and select Provides Namespace in the Utilities View:

enter image description here

You will see that the folder then becomes blue and you can see the path to the image above the images.

You can then access the image like this:

imageView.image = UIImage(named: "folder1/Image")

or in Objective-C:

imageView.image = [UIImage imageNamed:@"folder1/Image"];

Same name of two images in different folders of NSBundle

Here it is a very nice link for doing this task please check this
Xcode Groups vs. Folder References that clearly describe about it

Groups

  • The size and complexity of the underlying project file (project.pbxproj) can grow significantly, especially with multiple targets. Each new target has to duplicate all of the references. You also have to remember to set the proper target membership for each file. Plus there is a greater likelihood of SCM merge conflicts due to the larger and more complex project file.

  • Groups may bear no resemblance at all to the folder hierarchy on disk. You can have project folders in the Finder that don’t even exist in the Xcode project, and vice versa. Because of the mismatch, locating files can get confusing

  • If you move a file or rename it outside of Xcode, the reference breaks and the file turns red. File management becomes a real pain.

Folder References

The benefits of folder references are:

  • Xcode only stores a reference to the folder. All of its files and subfolders are automatically added to the project. This keeps the project file smaller and simpler, with less chance of merge conflicts.

  • If you rename, delete, or move a file in the file system, Xcode automatically updates the folder reference to reflect the change. File management is thus far easier.
    Because the folder hierarchy in the project matches the hierarchy on disk, they will not diverge over time and cause confusion.

  • You don’t have to worry about name conflicts because the directory structure is preserved in the product bundle. Two files can share the same name as long as they live in different directories.

How to use different assets with same name using multiple targets

You can do this by creating additional Asset Catalogs, these can be named accordingly, they will need to be added to your required target, Target Membership.

enter image description here

enter image description here

Having different collections you are able to have the same asset names and the targets will work as expected.

Referencing image in a folder in asset catalog

I spent a ton of time but finally figured this out. Answered here. Copied below.

Select each folder in your asset catalog that you'd like to add a namespace for. Go to the folder attributes and select under the name "Provides Namespace". This should properly set sub-directories for your final asset catalog.

You can do this manually by editing each folder's Contents.json. You would add the following with proper formatting.

"properties" : {
"provides-namespace" : true
}

How can I get all image names in asset catalog group?

So (following matt's suggestion) here is what I did:

I created a RunScript build phase to run before compiling

enter image description here

and used a script to create a txt file with the names of the files that I can then use during runtime

#!/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

Use multiple asset folders in xCode

Sprite Atlas / Sprite Sheet

You can use a Sprite Atlas (also known as Sprite Sheet).

If you don't know what I'm talking about have a look at these 2 nice videos:

  • Sprite Sheets - The Movie Part 1
  • Sprite Sheets - The Movie Pt. 2 - Performance

How to use it

If you have watched the videos now you know that the main target of a Sprite Atlas is loading into the GPU all and only (as far as possible) the images needed for the current scene or level. This way drawing each frame becomes much faster because all the resources al already on the GPU and the CPU only needs to transmit the coordinates.

Namespace

Ok but how does it solve your problem?

Xcode allows you to create a namespace for each Sprite Atlas. So you can use the same name for resources in different Sprite Atlas.

How to create a Sprite Atlas.

This is pretty simple.

  1. With Xcode open you Asset Catalog
  2. Tap on the + button you see in the image below

enter image description here


  1. Click on New Sprite Atlas
  2. You'll se a new "Folder", that's your Sprite Atlas.

enter image description here
5. Now click on the Provides Namespacecheckbox on the right.

That's it. Now just drop your images into the Sprites folder in order to add them to your sprite atlas.

In this example I'm going to rename the Sprite Atlas as Sprites0 and will add a red circle named circle.

Then

  • will create another Sprite Atlas
  • will check again the Provides Namespacecheckbox
  • will name Sprites1
  • and finally will add a green circle names circle.

Here's the final result

enter image description here

Code

Let's see now how to use it.

import SpriteKit

class GameScene: SKScene {

override func didMove(to view: SKView) {

let textureAtlas0 = SKTextureAtlas(named: "Sprites0")
let texture0 = textureAtlas0.textureNamed("circle")
let sprite0 = SKSpriteNode(texture: texture0)
sprite0.position.y = 100
addChild(sprite0)

let textureAtlas1 = SKTextureAtlas(named: "Sprites1")
let texture1 = textureAtlas1.textureNamed("circle")
let sprite1 = SKSpriteNode(texture: texture1)
sprite1.position.y = -100
addChild(sprite1)

}
}

Result

enter image description here

How does it work

Step 1: you load the Sprite Atlas

let textureAtlas0 = SKTextureAtlas(named: "Sprites0")

Step 2: you load a specific texture from the texture atlas

let texture0 = textureAtlas0.textureNamed("circle")

Step 3: you use your texture as you want

let sprite0 = SKSpriteNode(texture: texture0)
sprite0.position.y = 100
addChild(sprite0)

Accessing inner folders in Assets folder

This crash because you try force unwrap optional value.

UIImage(named: "logos/ca/payments/x.png") is optional value. Incase image doesn't exist in your project, this will be nil.

And we don't require put path when get image, just only image name and extension file like UIImage(named: "x.png")

Also cell.paymentImageView.image can accept nil image. So this line just only cell.paymentImageView.image = UIImage(named: "x.png") will be okey.

Hope this help!

Differentiating images in an asset catalog by their group

Select each folder in your asset catalog that you'd like to add a namespace for. Go to the folder attributes and select under the name "Provides Namespace". This should properly set sub-directories for your final asset catalog.

You can do this manually by editing each folder's Contents.json. You would add the following with proper formatting.

"properties" : {
"provides-namespace" : true
}

How to get Assets.xcassets file names in an Array (or some data structure?)

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)
}


Related Topics



Leave a reply



Submit