How do I use an external framework in my project?

Hi all.

Couldn't figure out any other category to put this in.

I haven't been able to use any third-party frameworks in an Xcode project. I've tried a couple of frameworks that were written in Swift (protobuf and AlamoFire), but any attempt to refer to them with an import statement results in "module not found."

Every reference I've found (including Apple's) says all you have to do is go into the target's "build phases" section in Xcode and add the framework under "Link binary with libraries." This doesn't work (not to mention that this area provides no way to identify which instance of the library is to be used with Release, Debug, Simulator, or Device builds).

I confirmed that the frameworks have contents and were built with "defines module" set to YES.

So... what is all this documentation leaving out? I'm not interested in using Cocoapods or any other package manager; I need to know the "native" solution and why this isn't working before relying on any third-party utilities.

Thanks for any insight!

I'd file this under "Using Swift."

Without looking at the documentation, the three basic steps are:

  1. Add the project file to your project files in Xcode (along with your source in the file view on the left).
  2. In Build Phases, add the library as a Target Dependency.
  3. Add the library to "Link binary to to Library".

I only see step three mentioned in your post.

I usually have to build the library target once before the parent project can find the module. The included project should show up in your parent project build schemes. It should also inherit the build environment of the parent (i.e, debug, release), but that can be customized.

Hope this helps.

Moved.

This is messier than you expect. The right answer depends a bit on exactly what you're trying to do.

Remember that you can only use a Swift framework if that framework was built with the exact same version of Swift as the one compiling your app. That means, in practice (for now), the same version of Xcode, and that in turn means you're better off (for now) building the frameworks as sub-projects of your main project (which is basically the solution that @brokaw suggested).

If, however, you really want to use pre-built frameworks (assuming you are ensuring Swift version compatibility), then you likely want to link them as *embedded frameworks. That is, you want to include those frameworks inside your built app. (Otherwise, you can link against them, but you would have to make sure they were already installed on the user's system in a standard location. This is not a direction you really want to go right now.)

To embed your frameworks, you shouldn't use the build settings directly, but go to the General tab of the project editor for your app target (select the project item in the navigator, then select the target in the editor pane, then select the General tab). Add your framework under "Embedded Binaries". It should then show up under "Linked Frameworks & Binaries" as well.

That much takes care of what you need to link your app, but it isn't enough to get your "import" statements to work. For that, you need to go to the build settings for your app target, and the "Frameworks Search Paths" in the Search Paths section. Add a project-relative path to your frameworks, if you don't see that Xcode has automatically added the correct path(s) already.

I believe that'll be enough to allow you to build your app.

Yes, that's a limitation of using pre-built frameworks. You don't get to specify which particular configuration of the framework build to use. If you need this, the only supported way is to add the framework projects as subprojects of your app project, which means that Xcode will re-build the frameworks whenever you change platforms (device or simulator) or configurations (debug or release) for your app project.

3 Likes

Thanks a lot for the replies, guys. Much more succinct than anything else that turns up on this topic.

I'm surprised at the limitations here. I remember building frameworks for device and simulator and specifying which one to use in each scheme... am I just imagining this?

And wasn't there a way to statically link against frameworks?

Anyway, I took your advice and followed the three steps you guys laid out; this worked. Thanks again for your time, and have a happy new year.