Is there a way to add multiple resources with the same name to an Xcode project and have 1 of them take priority over the others?
Example:
I added 2 files, both called icon.png, to an Xcode project. They are on different folders in the file system (Folder1/icon.png and Folder2/icon.png) and on different groups in Xcode. Is there a way to tell Xcode to have Folder2/icon.png take priority over Folder1/icon.png? And if only 1 icon.png exists, then use that one.
Thanks.
EDIT (2010-12-23):
You can have multiple files with the same name in an Xcode project even if they are not in separate folder references, but they are in separate groups. Once compiled, the app bundle (which will be flat with no folders in it), will only have one copy of the file (icon.png). How do you pick which copy of the file to use?
I was told that you can do this for BlackBerry. It works something like this: The compiler will go down the list of files in the project and start adding them to the app bundle. If it sees a duplicate, it will overwrite it (or not), so the files at the bottom (or at the top) will have higher precedence and will be the final bundle.
This can better easily be solved by using folders within a resource bundle in your Xcode project. Take a look here: http://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFBundles/Introduction/Introduction.html
Wait a second, since you specifically mentioned icon.png, are you trying to supply different iDevices (iPad, iPhone4, iTouch3...) with different icon images?
If yes, check this out, http://d.pr/W2w0 , Apple has already provided a way for us to finish this task with convenience. All you need to do is following a specific naming convention.
What we do if we have a situation like this is:
We have several subfolders on the file system level of the project dir and add them to XCode into separate groups.
This works well. For actually building, we try to avoid Files with the same Name in one target. Icon.png and iTunesArtwork are only added once in every target.
It just proved to be a Maintainability Nightmare
Related
I would like to localize some images in my iPhone project. So I created files:
en.lproj/Images/iPad/btn-check-pressed~ipad.png
en.lproj/Images/iPadRetina/btn-check-pressed#2x~ipad.png
ru.lproj/Images/iPad/btn-check-pressed~ipad.png
ru.lproj/Images/iPadRetina/btn-check-pressed#2x~ipad.png
and so on and added them to my project. But Xcode shows "English 0 files localized", "Russian 0 files localized" in Localizations list.
It also shows a warning
Warning: Multiple build commands for output file /Users/User/Library/Developer/Xcode/DerivedData/TestLocalizationDefaultPNG-ckplzmcjurofxrccjuvyzjaqketc/Build/Products/Debug-iphonesimulator/TestLocalizationDefaultPNG.app/btn-check-pressed~ipad.png
for each of my files when I try to build the project. So, as far as I understand, it copies all files in one folder, and since my files have the same names - only one of them can survive. But, if I remove my subfolders:
en.lproj/btn-check-pressed~ipad.png
en.lproj/btn-check-pressed#2x~ipad.png
ru.lproj/btn-check-pressed~ipad.png
ru.lproj/btn-check-pressed#2x~ipad.png
everything works fine.
Is there is a way to keep subfolders? Here http://developer.apple.com/library/ios/#documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html in Listing 2-4 subfolder used for the audio files, so it should be.
It looks like the only way localization works in iOS is different. You base folders hierarchy should be by inverted: first goes actual folders structure and in each and every folder you want to localize, you put corresponding .lproj sub-folder with localized resources. So in your example it should be something like:
/Images
/iPad
/en.lproj
btn-check-pressed~ipad.png
/ru.lproj
btn-check-pressed~ipad.png
/iPadRetina
/en.lproj
btn-check-pressed#2x~ipad.png
/ru.lproj
btn-check-pressed#2x~ipad.png
This might be sub-optimal if you intended to have big hierarchy but this is the only way it works out of the box.
Of course you can always say that you don't need Xcode support and use some custom build rules to re-arrange files in you project in the way you like and then copy them into proper structure during build but I doubt it worths troubles.
Update: it looks like XCode (4.5) build script is the main villain.
According to my experiments build script should flattens resources structure at least for images. So the only way localized app can be inside is:
/YourApp
YouApp
info.plist
....
/en.lproj
btn-check-pressed~ipad.png
btn-check-pressed#2x~ipad.png
/ru.lproj
btn-check-pressed~ipad.png
btn-check-pressed#2x~ipad.png
The trick is that by default XCode (as of version 4.5) can flatten your project structure only if it is as described above and I don't see a standard way to change this behavior.
Of course, original comment about custom build scripts is still true.
When doing iOS programming, it is interesting that in Xcode (4.3.2), we can create groups, such as a group call Images, and add files to it (either as a link or choose "Copy items into group's folder"). So it looks like a real folder in the navigator, and it even mentions "copy into ... group's folder", but in fact there is no folder. All added files are in the same location as the .m and .h files.
Why would we want Groups, but not real folder? Is there advantage of Groups over the use of a folder?
This is a pet peeve of mine.
I recommend, making the folder in your file system, where you have your project files, then drag that folder into Xcode where you want the group. It will act like any other group, but now be linked to the folder on the file system. Adding files to that group in Xcode now adds them to the folder in the file system.
Much cleaner way of working and helps when locating files in big projects. Keeps git cleaner too.
Update for Xcode 9:
Once you have the groups in Xcode matching the directory structure on disk, moving a file from one group to another in Xcode will now move the file correctly on disk to match.
Note: In Xcode 10, the default behavior now creates a linked folder when you create a new group. The information below still applies otherwise.
The recommended way to organize files is via groups, because it's more flexible than creating directories, and allows you to create complex file hierarchies while maintaining a totally different file hierarchy on the file system. It's simply an organization tool. That said, it is possible to turn groups into folder references, or create them initially as folder references.
Furthermore, using groups instead of folder references gives you greater flexibility if you need to change where things are in the file system - say you have a common folder of code that you use in a bunch of different projects. Groups allow you to organize the files inside of projects as if they were in the projects, while still maintaining one copy of the code in a central location. And yes, you can do this with folder references as well, but groups are much more flexible if you later want to add other things to the same group but don't want them to be added to that common folder.
If you want to link a group to a folder, click on the group in the project file tree and hit command+option+1. Below the drop down that'll say something like "Path: Relative to Group" on the right, there's a little white square with a grey border around it kinda icon next to the word "none". Clicking on this and then selecting/creating a folder will bind the group to the folder.
Furthermore, when you drag a folder into Xcode, it will ask you if you want it to be a group or a folder reference:
There is a Command Line Tool - "synx"
available in github that do exactly what you need.
It reorganizes Xcode project folder in finder to match Xcode groups in project.
You can find it here:
https://github.com/venmo/synx
UPDATE: XCode 9 supports this feature by default. So, no need to use other tools anymore!
Suppose that group A has its path set to folder A in the finder, and group B has its path set to folder B. I move one of my classes from group B to group A. Annoyingly, the default behavior is that the file remains in folder B in the finder, and Xcode sets the path for the file to something like "../B/ClassName.extension"
Is there a way to change this behavior so that in the above scenario, the file moves to folder A in the finder? Or, alternatively, a relatively painless way to move it afterwards?
There doesn't seem to be a solution to this - This is a similar question, but no one has come up with an answer there. How do i consolidate my xcode project files?
Seems like doing it manually is the only way to go unfortunately!
File grouping in Xcode isn't a reflection of the underlying file structure, nor does it particularly need to be. I've never understood there to be any real logic in where Xcode creates files within a project's directory, but I've never cared much because I can group them manually inside the project (not the filesystem) however I want.
I like to keep a store-bought version of my iPhone apps on my phone so that I can reproduce any customer issues that come up, but I obviously also want to run the most current development version. I can install both (one from iTunes, one from xCode) but I'm interested in ways that I'm better able to tell the two apart. I could just change the name or icon temporarily, but that doesn't seem very failsafe, i.e. I might forget and ship it with the wrong icon.
Is there a happy funtime developer way to do this?
I was inspired by Eric's idea of adding a user-defined setting to the project but I didn't want to run a script every time I built the project.
We know that the iPhone looks for icon files named "Icon.png" by default. It turns out that the "Icon File" setting in the project plist isn't necessary at all if you've named your icon properly. However, if there is no file named "Icon.png" in the project, xCode looks at the value of the "Icon File" setting.
I set a user-defined setting in "Debug" called "Icon_Name" to a non-standard icon name, "DevIcon.png" and "ReleaseIcon.png" for the "Release" config. The "Icon File" setting in the project plist can now be set to ${ICON_NAME} and will take on the value of whatever config file we're using. Now building under two different configurations does use two different icons.
Edit: For multiple icons (high res, small, ipad, etc) I made a slightly different approach. The user-defined setting is now "IconPrepend" which is "Dev" for debug and "Release" for release config. I'm now using "Icon Files" (rather than "Icon File") in the info plist which takes an array of strings. Each string is prepended with ${ICONPREPEND} so that debug configurations look for "DevIcon.png" or "DevIcon#2x.png" and release configurations look for "ReleaseIcon.png" or "ReleaseIcon#2x.png".
Here's an idea - if you set a User-Defined Setting in your Project Build properties for Debug only along the lines of USE_DEV_ICON=YES (or something). Then, using the "Run Script" option in your Build Target you could copy different icons based on which Active Configuration you called.
Something along the lines of (pseudo-code):
if ($USE_DEV_ICON == YES)
cp DevIcon.png Icon.png
else
cp RealIcon.png Icon.png
Then every time you build, depending on the active configuration, it will copy the correct icon.
Most probably there is no other way. Your app store version and development version is completely different to the OS. If you want to distinguish, you need to change the icon or name. You can also include some debugging label (e.g. version number) in your development version, but you may also forget to remove this.
Maybe you'd just buy a second iPhone? Seriously. On your place I'd ask the same question as you do, but I will definitely take such a solution in mind. If I was an iPhone (or whatever other specific platform) developer, I'd most probably have more than one.
Couldn't you make a new target which has a different Bundle name in the Info.plist file, and use this target whenever you want to build the app to run on your iPhone?
I searched for a long time on stackoverflow using every keyword I could think of to solve this. I am programming for iphone and I have a lite and paid version of my app. I followed the instructions here Creating Lite Versions of iPhone Games / Apps for duplicating the target. This works and now I am working on slimming down the lite version.
Main problem? Images. The lite version needs to have several hundred less images than the paid version. So, I made 2 groups in XCode. One "Folder Group" in Xcode - named "FreeImages" and another "ProImages". I want all FreeImages only to be included in the lite app and all FreeImages and ProImages to be in the paid app. I do not care that XCode considers these Groups to be Virtual Folders. I reversed the instructions to a point and have an environment flag (-D) set in XCode "PLUS_VERSION" I want XCode to basically do the following:
If (PLUS_VERSION)
{
copy contents of FreeImages *and* ProImages where normally they go
}
else
{
copy contents of FreeImages where they normally go.
}
Anyone know where to start to tell XCode to conditionally copy contents of groups into the target?
For each resource (or folder of resources) you want to direct to a specific target, you can click on the resource and inspect it (either via right-clicking and selecting Get Info or by clicking on the Inspect toolbar option). Within that info dialog will be a tab called Targets, where you can check the targets you want the resource (or even source code file) to be incorporated into, and uncheck the ones you don't.
Alternatively, I believe you can navigate to the target itself in Xcode, click on the triangle next to its name to expand the list of build phases, expand the Copy Bundle Resources build phase, and manually delete from the list there any resources you don't wish to have copied over into that target.