10

Trying to prepare a single dynamic framework to my customer. My framework (A.framework) uses third-party recognition static framework (B.framework). I can't provide separate A and B frameworks to the customer. Ideally B.framework should be built and included into my A.framework's binary, so the customer's app will only embed A.framework without any additional actions to link with that third-party app.

What I did:

  1. Added B.framework to the project.
  2. Added B.framework to "Linked Frameworks and Libraries" in the corresponding target.
  3. Built A.framework.
  4. Created a demo application and included A.framework to the project.
  5. Added A.framework to "Embedded Binaries".
  6. Demo app's build fails with message "Missing required module 'B'" (despite the fact that it is used in A.framework only).

Note:

  • I neither created any modulemap files for B.framework, nor additional run scripts
  • Making A.framework static is not acceptable because it includes some resources (storyboards, icons and some other files)
  • Tried to make un-recommended "umbrella" framework but got stuck on loading B.framework's bundle in demo app
  • Tried to make fake "umbrella" framework by simply copying B.framework inside A.framework, but got 2 problems - huge size of A.framework and Mach-O error while exporting the demo application (because of Mach-O difference between dynamic A and static B frameworks)

Any ideas would be highly appreciated!

UPD 1: This is not about umbrella framework because the proper umbrella framework implementation requires to load sub-framework from bundle which is not good. The fake framework implementation (sub-framework simply copied to umbrella) won't work for release because of different Mach-O values - dynamic and static. Plus fake umbrella framework has a huge size because sub-framework is being fully copied inside umbrella.

UPD 2: Created a small test project: StaticFrameworkTest which has 3 sub-projects:

  1. Demo-application with dynamic framework dependency (framework A) and shouldn't know anything about framework B
  2. Dynamic framework with static framework dependency (framework B) which ideally should be included in A framework's binary.
  3. Static framework B
semenchikus
  • 730
  • 8
  • 17
  • Do a small demo project with 1 file in framework A and 1 file in framework B. It would help you understand and also others understand – user1046037 Jun 22 '18 at 12:46
  • 1
    Possible duplicate of [How to create an umbrella framework in iOS SDK?](https://stackoverflow.com/questions/27484997/how-to-create-an-umbrella-framework-in-ios-sdk) – Rei Jun 22 '18 at 14:35
  • @Rei no, it's not about umbrella framework because all the ways to implement umbrella are not proper solutions for release version. Please see UPD 1 with a bit more detailed explanation. – semenchikus Jun 25 '18 at 10:12
  • @user1046037 thank you for your reply! Please see UPD 2 with link to the project – semenchikus Jun 25 '18 at 10:14
  • @semenchikus In your project where have you defined `TestDynamic`. I couldn't spot `TestDynamic`. Create a workspace and add the framework and TestApp's project file on to it. Refer: https://www.raywenderlich.com/126365/ios-frameworks-tutorial – user1046037 Jun 25 '18 at 10:21
  • @user1046037 sorry, but I don't want to link TestApp and DynamicFramework projects with each other because the idea is to deliver the dynamic framework to the customer. Please check if DynamicFramework.framework is in "Embedded Binaries" of TestApp's build settings ("General" tab). – semenchikus Jun 25 '18 at 11:23
  • @user1046037 do you have any ideas how to resolve the problem? – semenchikus Jun 26 '18 at 14:57
  • First creating a workspace doesn’t remove the demarcation still they are different projects, you can always select the scheme for the framework alone and build only the framework. Secondly hope you know the differences between static and dynamic frameworks. If you don’t want to expose the code then you could create a static framework of A that contains that static framework B – user1046037 Jun 27 '18 at 00:04
  • Can you just use cocoa pods, you can add dependency frameworks to your podspec so the thirdparty framework is always available with your framework – Justin Miller Jun 27 '18 at 10:22
  • @JustinMiller, unfortunately not. The client who use my dynamic framework doesn't use cocoa pods. – semenchikus Jun 27 '18 at 13:01
  • @user1046037, so if they are different projects, the common workspace is not necessary, right? I just want to keep it similar to the real example, where I'm using third-party static framework (no access to source code) in my dynamic framework and then publish my framework to my clients who are using it again without sources. – semenchikus Jun 27 '18 at 16:18
  • Please refer to the documentation would help you. – user1046037 Jun 27 '18 at 16:20
  • @user1046037, yes, I understand differences between static and dynamic frameworks. Making my framework (B) static is not allowed because it consists of other resources (storyboards, license file, etc.). – semenchikus Jun 27 '18 at 16:20
  • @user1046037 I couldn't find any appropriate documentation for my case. That static framework is actually Objective C static library wrapped into framework. When I've unwrapped this library with headers and included into the project, I've faced "Missing required module B" error again. I followed the following links to import the library: http://ioscake.com/importing-commoncrypto-in-a-swift-framework.html https://stackoverflow.com/questions/42085217/swift-project-missing-required-modules-when-import-a-modular-framework http://nsomar.com/modular-framework-creating-and-using-them/ – semenchikus Jun 28 '18 at 06:34

1 Answers1

4

A static framework is by definition a fat static library combined with any additional required resources. As such you can embed your third party static library inside your own and also include images, storyboards, plist etc.

You can't do that in a static library (i.e. *.a), but in a static framework you can do. See for example https://www.raywenderlich.com/65964/create-a-framework-for-ios for details on how to do that (at the end of the article it creates the static *.framework out of the static *.a and some resources)

A dynamic framework can never embed a third party static library. The main application that imports the dynamic framework will always have to also explicitly link against the static library, which it seems that is not what you want.

Gabriele
  • 138
  • 4
  • Thank you! Finally, I was able to build static framework with all the dependencies and resources without any issues. Who will do similar stuff, note: an application that depends on a static framework should be only linked with this framework (not embed it), plus "Framework Search Paths" setting for the application should be set to all the inner frameworks. – semenchikus Jul 03 '18 at 09:23
  • 7
    **> A dynamic framework can never embed a third party static library.** I think that is an incorrect statement. A dynamic framework *can* embed a static binary (library or framework) and then you the App does not need to know anything about this static dependency. Static binary would then be embedded == merged with dynamic binary symbols, exactly the way static binaries always do. I couldn't find a doc proving or disproving that but we have exactly this setup in our project and it works. – Oleksandr Yefremov Jan 30 '19 at 12:15
  • 1
    You are actually right. It is possible to set it up. But you do still incur the risk of symbol duplication so unless you control the entire app and you can guarantee that's the only place the binary library is imported, it is not a recommended approach. – Gabriele Jan 31 '19 at 13:08
  • @semenchikus please let me know if you able to fix this i got same issues – Krishna kushwaha Jan 16 '21 at 07:44
  • How can I use pod or Firebase or some 3rd party libs in a dynamic framework? – kent2508 Feb 02 '21 at 08:02