Loading code from a framework for a custom control

2019-02-15 06:17发布

问题:

I've implemented a custom control in a OS X application that works fine. When the control is drawn it uses code from a non system Framework. The control is written in swift, the framework is in Objective-C. The Framework is not built in the same project or workspace as the application with the custom control. I've added the Framework to the target and added it to a copy files build phase.

When I add the IBDesignable decoration to the custom control class in swift then I get an error when trying to view the control in Interface Builder. The error I get is:

file:///Users/ktam/github/MovingImagesDemo/Spinner2/SpinnerController.xib: error: IB Designables: Failed to render instance of Spinner: dlopen(Spinner2.app, 1): Library not loaded: @executable_path/../Frameworks/MovingImages.framework/Versions/A/MovingImages Referenced from: Spinner2.app Reason: image not found

When I check the application bundle created in the IBDesignables sub folder the framework is in the correct place in the application bundle. I'm assuming that the executable actually being run in this case is not the one in the IBDesignables application bundle but possibly an Interface Builder executable of some kind which explains why the Framework image is not able to be loaded.

What do I need to do to load code that Interface Builder can find when it renders a view with IBDesignable?


Info after further testing:

I rebuilt the Framework while specifying the installation directory to be ~/Library/Frameworks and then copied the built Framework to that location, I then updated the application target so that the Runpath search paths included ~/Library/Frameworks and both the Application and Interface Builder draw the custom control correctly now.

This is not the solution I need but it points to what the problem is, I still need to work out what the proper fix is.

回答1:

The solutions is to set the Installation Directory build setting for the Framework target in Xcode to @rpath. Then in the Xcode project that builds the Application add to the "Runpath Search Paths" build setting of the Application target the value: @loader_path/../Frameworks.

Using @rpath instead of @executable_path is much more flexible.

The two blog posts that helped me work this out are:

Using rpath by Dave Dribin

and

Linking and Installing by Mike Ash