According to this
Most public frameworks should be installed at the local level in /Library/Frameworks
That's our goal here. Any app that launches and then needs to find a framework should find it by searching "the usual suspects". According to the docs, the best place is
/Library/Frameworks
, but here I will use ~/Library/Frameworks
.Such a framework would be a dynamic framework, not static, or baked into the app. If you were to write an installer for such an app, you should take care to install its frameworks in the right place. R is a great example of how to do it right.
So in Xcode:
OS X > New Project > Framework & Library > Cocoa Framework > Swift
I named it SpeakerFramework.framework. Add to the framework a new Swift file
speaker.swift:
Having the
init
and speak
functions both public (as well as the class itself) is required for external visibility (ref).Build the framework.
Under Products, find
SpeakerFramework.framework
. Control-click and show in Finder
then drag it to the Desktop.
For what we will do in a minute, we need the Finder to show
~/Library
in an Open File dialog. With your home folder selected in Finder, do CMD-J (or View > Show View Options) and select Show Library Folder. (If you are just on the Desktop, then Show View Options shows something different).Now for the app. In Xcode:
New Project > OS X > Application > Cocoa App > Swift
I named it
MyApp
. In AppDelegate.swift add
import SpeakerFramework
This import statement gives an error and the project will not build (No such module 'SpeakerFramework').
To fix this, open
~/Library/Frameworks
and drag the framework we just copied to the Desktop into that folder. Alternatively, just do this in Terminal:
cp -r SpeakerFramework.framework ~/Library/Frameworks
Now, back in Xcode, select the project in the Project Navigator. In the tab view, select General and scroll to the bottom where it says Linked Frameworks and Libraries.
Click the + symbol below that line (not shown in the screenshot, because I only took it after I added the framework to this project).
Click Add Other... Then navigate to the framework in
~/Library/Frameworks
and select it.The MyApp project shows the framework in the General tab
Go back to the AppDelegate. The warning should be gone.
MyApp will build now. So let's use it. Edit the AppDelegate to call the
speak
method:In the Debug window, we can see the expected output.
It would be nice to make a bigger statement.
I'll just outline the steps briefly. Delete the default window in
MainMenu.xib
. Add a new Cocoa class, subclassing NSWindowController. Have Xcode make the xib file too. Drag a label onto that window. Make it really, really big. Hook it up to the new class (MainWindowController) as an IBOutlet, with this code for the AppDelegate:
and for MainWindowController:
Pretty impressive:
If we select Products > MyApp.app, then show in the Finder, and drag it to the Desktop, and delete everything else, except the framework in ~/Library/Frameworks, it still works. If we then do
> mv ~/Library/Frameworks/SpeakerFramework.framework/ old
> ls ~/Library/Frameworks
>
So it looks like everything is working as expected.
I thought I would snoop on the Loader as I did long ago:
> export DYLD_PRINT_LIBRARIES=1
> open -a MyApp.app
But it gives nothing. I am not sure why, yet.