We often want to share code between our different projects and the different platforms. How do you set up your framework to compile for both Mac and iOS in such a way that the code that consumes that framework can be common too (i.e. just have a single import MyFramework line)?
The solution doesn't require, but benefits from, a little thought on the structure of things.
1. Create a workspace
Firstly create a workspace in XCode and put it in its own folder, this is important because it helps if you can "branch" the different projects contained from that root folder
2. Create a Group and Folder for Common Code
We will want to share as much code as possible between the two builds, and I like to have this code in the workspace itself to make that really clear.
Create a new group in your new empty workspace
Then add your swift files to it, we recommend creating them in an appropriately named sub-folder of the workspace
We're going to keep it simple for this one class... here's what you should have now
3. Creating the Mac and iOS Frameworks
Right, now we want two framework projects, one for the Mac and one for iOS. We want them in different projects because two targets can't have the same name in the same project.
You can use the menus to create a project, but it's easy to add it to a workspace with the + button in the navigator.
Again, create a meaningful folder for the two of them... first the Mac
Note the Add to: and Group: fields as well; we want the project to appear in the workspace. Now do the same for an iOS framework project
Again... note three things
- The iOS framework project has it's own folder. This is not required, but strongly suggested for your sanity!
- It's added to the workspace NOT the Mac project we created earlier
- It's in the workspace grout NOT the Mac project we created earlier
4. Adding the common source to both projects
You will now have two projects in your workspace, and your common code.
We want the same .swift files compiled into the module for both frameworks. This is why we added a folder for the common code. We will do this by adding a folder reference to the Mac framework (you will then repeat these steps for the iOS framework) project, then making sure its contents are built.
First right click on the Mac SwiftKit project and pick Add Files to "SwiftKit"...
We select our Common code folder to that anything in there will be built into the framework.
Note we have unchecked Copy items if needed and have selected Create folder references. We only need it added to the framework target, not the tests. You should have something like this
But we have a problem, right now, the Swift files in that folder will not be compiled, you have add them to the Compile Sources phase of the framework. To do this, select the SwiftKit project (Mac) and select the framework target. Go to Build Phases, and open the Compile Sources phase (note it says 0 items right now). Click the + button
And then pick the Common folder reference you have added (or whatever you called the folder). Now as you add files to that Common folder they will automatically be added to your Mac framework.
5. Repeat for iOS Project
You should end up with the following (don't forget to add the folder reference to the iOS project too).
6. Using the your framework in an App
You will probably want to actually make use of the framework now! It's very easy, let's look at the simplest case, adding the framework to an OS X command line app. Create a new project as an OS X->Command Line Tool. Again, we strongly recommend creating a new folder in the Workspace folder to contain anything specific to this project
Again note that it is added to just the workspace, not the contained projects. Now we need to add the Mac framework to that project
First pick the Mac Framework target's output, and reveal it in the finder
Then drag it into your command line app (if you are doing this for a Cocoa or UIKit app you can just add the framework as normal too)
We can now add some code to our main class to test
It's that simple. We can now use our common Mac and iOS pure swift framework in whatever other targets we want. Simple.