In this post, i want to talk a bit about another feature of Elements called Shared Projects.
Shared Projects are a way to have pieces of code and easily share them between multiple projects. This can be helpful in many scenarios, the most common being that you might create apps for two or more different platforms. But they also come in handy even for single-platform devs – for example you might be writing a console all and a GUI application that exppose common logic.
Of course on a single platform you can always opt for a more traditional library project, but Shared Projects have advanatges there too.
What is a Shared Project
In essence, a Shared Project on its own is simply a container for one or more source (or, in theory, other) files. Shared Projects don't have any settings, they don't have a specific platform, and they don't actually compile code, themselves. They just hold a collect of files in a group, and of course let you work with them in the IDE.
For the purpose of this article, lets assume you have an iOS and an Android app, and you want to add some shared business logic code (say, talk to your server and download a JSON file with data) that you only want to write once.
So right now, your solution would look something like this:
Go to "File|New Project..." in the menu, or right-click the empty spavce below the porject tree, and choose "New Project...", there. In the resulting dialog, select "Shared Project" from the dropdown (it should be available regardless of the selected platform tab), and make sure that the "Add to existing solution" is checked. Click "OK" and save the project in a convenient place.
Your solution now looks like this:
You have the extra shared project, recogizable by the white icon. But it's not actually used by anything, so if you build your solution, the code in the shared porject won't actually compile yet.
Referencing a Shared Project
To let Elements know which of your projects (in this case both) want to make use of the shared code, simply pick up the Shared Project node with the mouse and drag it on over to the "real" project that should reference it. You can drop either on the project node itself, or on its "References" folder.
You will see the shared project show up in references as a rectangular "project"-style icon.
Repeat this step to add a reference to both real projects:
When you now build your solution, you'll noticde that the Shared Project still does not build on it's own. But each of the projects that reference it are now pulling in the source file(s) from the Shared Project:
When working in a cross-platform project, you will often not want to build all projects for each change you make, because that adds extra overhead to seeing your result on the one platform you are currently testing, or to seeing any code errors you made. This is especially so once you start working in the shared files, because a single chnage – of cource – now affects every project that pulls in that file.
Luckily Fire and Water make it easy to enable and disable projects as you need, by right-clicking them and toggling "Enabled", or choosing "Enable only this Project" from the context menu.
(When you Run or Test, Fire and Watwer will also smartly only build those projects needed to run your current build target; but when you press Build, a common thing to do, especially in the early phase of coding when you don't expect your code to fully compile and run yet and just want to see if it compiled, manually enabling/disabling projects can be helpful).
Because, as mentioned before, Shared Projects don't get compiles themselves, they play a special role in the enabling/disabling mechanism. In particular, a Shared Project cannot really be enabled or disabled, itself. Instead, a Shared Project will show as enabled as soon as one or more project that reference it is enabled. And toggline the "Enabled" state of a shared project via the context menu will in fact toggle the satte of all projects that reference it.
Working in Shared Files
Of course as far as working with, and particularly, writing code code in Shared projects goes, they behave just like any other "real" project. You see all the files that are part of the Shared Project in the projetyc tree, can select them and start coding. You can add new files or rearrange files within a shared project the same way you would in a "real" project.
But here's the dilemma: You start typing code in a shared file, and you invoke, say, Code Completion by pressing CC. The shared project, though, has no concept of what platform you're even coding for, let alone what to show for CC. And, to boot, if your Shared Project is used across platforms – what should CC show, in addition to your shared classes? Should it show available iOS APIs, or Android ones?
Fire amd Water solve this by letting you choose which projects' context tyou want to work in for a file, at the given moment.
The first time you invoke CC (or any other command that depends on code context, such as "Go to Definition" or the like) in a file, the IDE will not actually show you the CC dropdown list, just yet. Instead, it will show you a drop-down we call the "Project Picker":
Here you see a list of all the "real" projects that reference your Shared Project, and you can select one to work with. Once you make a selection (simply down-arrow to the right project and opress Enter), the IDE will show you Code completion (or perform whatever other action you asked it to.
It will also persist the selection of the active project for the file, for any future use of the IDE smarts.
Of course you can always invoke the Project Picker again by pressing ⌘⌥P (Fire) or Ctrl+Alt+P (Water). You can also see the currently active "work in" project in the solution tree, and you can right -click either a single file or the whole project there to change it.
If you have a Mac with a Touch Bar, the Project Picker will also appear there, when you first invoke CC or when you invoke ⌘⌥P.
This way, you can switch back and forth between platforms as you code.
Of course most of the code you'll write in shared files will be, by its very nature, using shared classes and possibly Elements RTL, so often the distinction of active prject is unimportant. But you'll also have the occasional conditional per-platform code where it matters to see the right stuff in CC..