When adding a folder to an Xcode project, you can add it as a group or as a reference.
What’s the difference, and why would you choose one over the other? Each has advantages and disadvantages, some of which are quite subtle.
Groups
With groups, Xcode stores in the project a reference to each individual file. This can lead to problems:
- 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.
In exchange for these annoyances, groups give you some advantages:
- You can pick and choose which files on disk you want to appear in the project. There may be auxiliary files such as documentation that you don’t want to appear in the Xcode Project Navigator.
- You get fine-grained control over target membership. You can, for example, exclude a single file from a target.
- When building the product, Xcode flattens the group hierarchy and dumps all the files in the top level of the product’s bundle. You don’t have to specify the location in the hierarchy. For example, instead of:
[UIImage imageNamed:@"Images/Icons/GoPago"];
you can just do:
[UIImage imageNamed:@"GoPago"];
But this does mean you have to resolve conflicts if two images happen to share the same name.
Folder References
Folder references are simpler. You can spot a folder reference because it shows up in blue instead of yellow.
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.
So why don’t we always use folder references?
- Target membership is coarse-grained. Either all of the files in the folder are in the target, or none are. (On the other hand, if you actually want all files in the folder to have membership, this could be more of a pro than a con.)
- There is no way to hide individual files from the project navigator. Either they all appear or none do. (Again, this could in fact be an advantage because there’s no way for a file in the folder reference to be accidentally left out of the project.)
- When loading a resource, you must specify the full path. Instead of:
[UIImage imageNamed:@"GoPago"];
you must do:
[UIImage imageNamed:@"Images/Icons/GoPago"];
And if you change the file’s location on disk, you must remember to update the code.
- An image stored as a folder reference will not work with Interface Builder! When editing, IB is able to find the image file and allows you to select it, but when it generates the XIB, it strips the folder location, which prevents it from being found. The result is a blank image and a runtime error:
Could not load the "MyImage.png" image referenced from a nib in the bundle with identifier "com.mytest.MyProject"
Conclusion
The fact that Interface Builder can’t work with images in (sub)folder references is a dealbreaker. And being able to select the target membership for individual files—a feature only provided by groups—can be very useful. For these reasons, you will find that groups are far more common in practice, and it is the option I recommend. You just have to live with the fact that if you move the files around on disk, you’ll have to manually update the Xcode project to match.
That said, it’s unfortunate that Xcode doesn’t offer better support for folder references. I wish I could use them more often, as I hate having to keep my project view in sync with the filesystem, but the IB problem keeps me away. And I almost never need groups, since my projects typically have only one target, and pretty much everything in my project folder gets bundled into the product. Maybe one day Apple will fix the IB bug and my wish can come true.