Xcode -using two xcassets how would i override - ios

Let me explain the architecture i'd like to build in xCode. here is a photo of xcassets i have created in the project structure:
From the image you can see that i have created two xcassets folders. The first one called images.xcassets hosts all images that are common to both my targets.Its membership is in both target1 and target2. This xcassets sheet is filled with many images which i inherited from a fork.
The images-override.xcassets folder on the other hand, is where i'd like to put any images that ARE NOT common to both my targets. So the target membership for this directory should be only target2.
What im trying to accomplish:
Doing it this way, if i attempt to retrieve an image called myImage.png it should first check the images-override to see if any image is overriden, if its not found there it should then check images.xcassets for the image.
So my question is about what order the images will get searched for. I'd like the project to first check the images-overriden.xcassets sheet then check (if necessary) the images.xcassets folder. Any ideas ?

In general, you cannot include multiple assets with the same name in Xcode. For your purpose, I'd recommend a naming convention:
filename.png
filename-override.png
For example. When loading your image, you first check if filename-override.png exists, if so load it. If not, load filename.png.

Related

Create file reference to image in Images.xcassets using xcodeproj

I'm writing a script with Xcodeproj and I would like to create references to image files inside .xcassets. Finder treats .xcassets & .imageset as Folders but I don't want to create a group in xcode for each of those folders.
I'm able to create a reference when I know the containing groups in Xcode. i.e. project.main_group['Src'].new_reference(pathToProject/Src/fileName.m)
I'd like to iterate through the sub-directories and files of .xcassets and create a reference for each image. But I don't want to create a group in Xcode that matches each imageset in Finder because Xcode deals with the .xcassets folder in its own way.
I would like to be able to do something like this:
project.main_group['Src']['Images.xcassets']['image_name.imageset']
.new_reference(pathToProject/Src/Images.xcassets/image_name.imageset/image_name.png)
The above line doesn't work using Xcodeproj because it can't find any Groups named Images.xcassets or image_name.imageset.
Can anyone point me in the right direction or give an example of how I would create a reference to an image file stored inside Images.xcassets?
Thanks for your time!
It turns out Xcode handles the image references for you if you add an .xcassets file to your project.
Another thing I learned is that the .xcassets folder should be added to your target(s) as a resource with xcodeproj instead of a file reference. That way it will correctly show up under Project -> Target -> Build Phases -> Copy Bundle Resources.
e.g. target.add_resources([file_reference_to_xcassets])
instead of target.add_file_references([file_reference_to_xcassets])
Hopefully, this helps someone down the road :)

Using XCAssets Properly (adding assets)

I had two people discuss two different approaches with me on how to add assets such as images to a project in Swift.
Person 1: "You should create a new folder within your actual project workspace and then add all of your assets to it directly (so it's within the project). Then drag & drop the assets from this project folder to XCAssets, to actually create the icons you will use."
Person 2: "Just download your images from wherever, and drag and drop them directly. They can be from different locations. When you deploy to ITunesConnect it will copy the images."
Now I'm confused - when I drag and drop an image (let's say from my Downloads folder) doesn't Xcode copy the image locally into its own private location? Once I drag it into XCAssets, does it need that source location anymore? I thought maybe approach #1 would end up forcing Xcode to store duplicate images/assets and take up more size on the app.
What is the "correct" approach to adding assets?
Thanks!
Both actually can work (drag and drop/use asset folder). But the latest method introduced by Apple by xcasset folder. XCAsset folder is superior in the way that you can see a list of assets nicely one by one, even you have multiple sizes on it (.png #2x.png #3x.png etc). Easier to manage and see which size you are missing etc.

Storyboard, UIImageView. Load image from bundle

My issue is:
I have several projects/targets with shared xcassets.
What I want to do is to set images inside storyboard without code.
As I was able to find, there are no way to set image in storyboard from different bundle.
I created UIImageView extension, but don't think about like the best solution.
Is there exist a way to use assets in storyboard from different bundle?
Thanks.
So, based on answers to this question, I do know of one solution. Sounds like you've already done some of this, but just in the interest of giving a complete answer:
Create a framework project to house your shared images (it's great for shared code too!): File > New > Project > iOS > Cocoa Touch Framework.
Create a new Asset Catalogue within the framework File > New > File > iOS > Resource > Asset Catalogue.
Import your images into the Asset Catalogue.
Create a new workspace: File > New > Workspace.
Add both your app and the framework to the workspace: File > Add Files to WorkspaceName.
Include the framework as an 'Embedded Binary' within the app's project: Click the blue project file icon in the project navigator, go to the General project settings and locate Embedded binaries. Click + and select the Framework from the list (e.g. ExampleFramework.framework).
The above should be enough to allow you to use images from the framework's Asset Catalogue when they are called using code...
let frameworkBundle = Bundle(for: FrameWorkClass.self)
guard let image = UIImage(named: "MyImage", in: frameworkBundle, compatibileWith: nil) else { ... }
...however, to use it in a storyboard or XIB, there's one more step needed. Whilst the image names will now be selectable from Interface Builder (and even display there when selected), storyboards can only reference their own bundles, so it'll give you the following error when the app runs, and the image will be missing:
Could not load the "ImageName" image referenced from a nib in the
bundle with identifier "BundleName"
To fix this, you need to go to the Workspace's navigator (left panel) and drag the Asset Catalogue (i.e. the .xcassets file) from the framework to somewhere within the app project itself (e.g. the project's root folder).
In the dialog that appears, be sure that your app is checked in the Add to targets list, and that you leave the following option unchecked.
This will create a reference in your app's main bundle to the Asset Catalogue in the framework, but without creating a duplicate of it.
Once you've done that, you can use the images from that catalogue just like any other within your storyboards & XIBs.
Honestly, I can't vouch for if this is a best-practice, but it's the only way I've found to achieve what I also feel to be a sensible means of minimizing duplication between projects. In case you're interested, I've posted a question here to try and determine if this causes any duplication of the assets on build.

Can I access an xcassets directory on the filesystem?

I would like to dynamically load all images in an xcassets directory. The files are named StockPhoto# where # is the number in the list. If I can access my StockPhotos.xcassets at runtime to count all the files in the directory, I won't have to manually load the files each time I add new stock photos.
If there are other solutions to this problem, I'm open to that but I'm also just very curious how xcassets are handled by the file system- whether they're just reference to a set of files, or actually their own directory. Information on this is sparse.
If there are other solutions to this problem, I'm open to that
The problem is that there is no introspection at runtime into an asset catalog: it isn't a "thing" you can "see" as far as Objective-C and Cocoa Touch are concerned.
The usual solution to this kind of problem is to drag a folder full of images into your project at the outset, and when you do, choose "Create folder references for any added folders" in the dialog - not "Create groups for any added folders". The result is that the folder is copied into your app bundle, and now you can use ordinary file system methods to say "every file in this folder".
Upon compilation of your iOS project, xcassets are compiled to produce either image files, or a proprietary .car file. In that latter case images won't be stored in a directory you can browse.
If your "Deployment Target" is less that iOS7 (meaning that your app would still be able to run on iOS6)
It will produces the same set of image files that you would have had to produce without using Assets Catalog, namely <YourImageName>.png, <YourImageName>#2x.png, <YourImageName>~ipad.png, <YourImageName>~ipad#2x.png and so on, for each image set of your xcassets.
If your "Deployment Target" is iOS7 or greater (meaning that your app would only be able to run on iOS7+)
It will produce a single big .car file in the final bundle (I don't really looked up if this file was actually an sqlite3 datatbase or some proprietary format or whatnot, but who cares, you are not supposed to manipulate it anyway). This big .car file contains all the images, with all their provided variants, and even with slicing info (if you did slice some of them for tiling or to use them as 9-patch images using the tool provided for that in the Assets Catalog editor)
Whatever the produced result you shouldn't / are not supposed to dig into internal details of your bundle like that. The format of the .car file may even change from one iOS version to another (who knows? that's internal details after all which we shouldn't have to deal with) so don't base your logic on it.
[EDIT]: If you need to be sure to have a directory with your set of images at the end of the compilation, you could instead use a folder reference (referencing a real folder in the Finder, as opposed to an Xcode "group" as only group files in Xcode's Project Navigator) then use code to browse it. But then you will have to deal with other details, like only browse files that match the current device (iPhone vs. iPad, non-retina vs. retina…), so this would only shift the problem further in your case; you really should use a constant somewhere to declare the number of images (or put this in some PLIST file for example) and iterate thru them.
As the files you provide at compile time will be in your Bundle — which cannot be altered once compiled as it is digitally signed — the number of images will never changed once the app is compiled anyway. (That's not like if you used the Documents directory and enabled iTunes File Sharing or whatever, letting the user add images himself ;-))
If you're targeting iOS 7+ then no. Xcode will package the files into a proprietary format (.car) that you can't access directly.
Either use imageNamed: methods, or don't use Image Catalogs for the files you need to access directly.
as #AliSoftware suggests you can store all assets images to plist and access them later for more details see here

One Project For Multiple Applications in XCode

I am trying to use the approach of having a single project that uses different targets with different plist files. However, each target has a different set of launch and icon images. I cant however use a duplicate set of these since adding a duplicate image when the same name gives the error that its already in use. Is there anyway around this in xcode?
To save the file, either provide a different name, or move aside or delete the existing file, and try again.
You should use Xcode 5's assets catalogs. You can define a different assets catalog for each target, and in each assets catalog you can define different launch images. Names are handled by the content generator.
You can mix asset catalogs, so you can have, for example, one shared catalog for shared images, and individual ones for each different target, where you can have distinct icons and launch images.
OK, so I have changed my approach and found the easiest and a simple solution which I ignored before. All you have to do is keep the file names same but keep the files in different folders. And when adding them to project, check the target to which the files belong to and uncheck other targets. See the image.

Resources