Kodeco Forums

Creating and Distributing iOS Frameworks

In this iOS frameworks tutorial, you'll learn how to take advantage of native iOS frameworks to modularize, reuse, and redistribute your code.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/1107-creating-and-distributing-ios-frameworks

first, thanks for the article, nice introduction and step by step guide…

the question I have is how to build a framework that combines both the device and simulator targets, so when I ship the framework to a 3rd party, they can use it both on the simulator and device?
I’m not releasing the source code (well, my client isn’t, same difference), so setting up a repository and using cocoapods (which I’m not a fan of anyway) is out of the question.

thanks in advance for any additional info

You can make a framework that works on both the simulator and the device. For that, you will need to:

  • Build the framework twice using the CLI (once for the device architectures, once for the simulator architectures), for example:

xcodebuild archive -project $FRAMEWORK.xcodeproj -scheme $FRAMEWORK -sdk iphoneos SYMROOT=$BUILD xcodebuild build -project $FRAMEWORK.xcodeproj -target $FRAMEWORK -sdk iphonesimulator SYMROOT=$BUILD

  • Combine both build into a single .framework:

cp -RL $BUILD/Release-iphoneos $BUILD/Release-universal lipo -create $BUILD/Release-iphoneos/$FRAMEWORK_PATH/$FRAMEWORK $BUILD/Release-iphonesimulator/$FRAMEWORK_PATH/$FRAMEWORK -output $BUILD/Release-universal/$FRAMEWORK_PATH/$FRAMEWORK

You can combine these commands into a script to generate your framework when you need it.

However, if you generate your framework like this, the project that will integrate the framework will need to remove the simulator architectures when submitting to the App Store. Otherwise, your build will be rejected immediately. There are no other solutions that I’m aware of if you want to ship a .framework without the source code.

In order to prevent this, you should create another script that will be added as “Run Phase” in the project that includes the framework. Here’s the one I use:

FRAMEWORK=$1 echo "Trimming $FRAMEWORK..." FRAMEWORK_EXECUTABLE_PATH="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/$FRAMEWORK.framework/$FRAMEWORK" EXTRACTED_ARCHS=() for ARCH in $ARCHS do echo "Extracting $ARCH..." lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH" EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH") done echo "Merging binaries..." lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}" rm "${EXTRACTED_ARCHS[@]}" rm "$FRAMEWORK_EXECUTABLE_PATH" mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH" echo "Done."

Make sure you add this script as a resource in your framework.

Your Run Phase should look something like this:

bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/MyFramework.framework/ios-strip-frameworks.sh" MyFramework

Regarding Cocoapods, also know that it is possible to distribute pre-compiled .framework with it (but it will only work on iOS 8 and later). You’ll need to do is define a direct URL to the zipped .framework in your Podspec. More infos are available on the Cocoapods website.

1 Like

thanks a lot, will try this out tomorrow (it’s the middle of the night in Slovenia :wink: )

Nice tutorial.

I just want to know, if I need to add Coredata using pod distribution, will it be similar like mp3 section

s.resources = “ThreeRingControl/*.mp3”

Thanks for the answear, I have a really similar problem too. I think it’s a bit strange to ship a framework with a script to be able to actually use it. As far as I know e.g. facebook ships their SDK in a .framework, but they don’t need any script, besides it can be used in simulator.
Does anybody has any idea how are they doing it?

Thanks

Facebook indeed ships a universal framework. Did you successfully submitted a build to the App Store with it?

PSPDFKit also requires you to use the same sort of script when integrating the framework manually: Getting Started with PSPDFKit | PSPDFKit

1 Like

Not yet. But I didn’t found anybody complaining about beeing unable to send an iOS app to review 'cause the facbook sdk. :confused:
Otherwise thanks for the link, the built in script seems a bit sophisticated solution than giving the full “strip.sh”

@mkatz Hi. I am not able to install the pod in the final step after publishing it to my github account. I am getting the following error:

[!] The ThreeRingControl pod failed to validate due to 1 error:
- ERROR | source: The Git source still contains the example URL.
- WARN | source: The version should be included in the Git tag.

Could you please guide me in the right direction.

There is a small gotcha, you also have to copy over the *.swift[doc,module] files for the simulator:

cp $BUILD/Release-iphonesimulator/$FRAMEWORK_PATH/Modules/$FRAMEWORK.swiftmodule/* $BUILD/Release-universal/$FRAMEWORK_PATH/Modules/$FRAMEWORK.swiftmodule

If you don’t, a project using the resulting framework, when building for the simulator, will not be able to see the classes contained in the framework…

otherwise, works like a charm… thanks, again :+1:t3:

the thing I did “wrong” was that I did a build for both targets, not an archive… oh well :wink:

@pai
In ThreeRingControl.podspec, set the `source line to the URL and tag for repository.

E.g.

s.source       = { :git => "<#YOUR GITHUB URL#>", :tag => "1.0.0" }

Great tutorial. The one thing that’s typically never discussed is best practices when depending on external frameworks when creating your own framework. For example your shared code will utilize AlamoFire or in my case the frustration of depending on CocoaLumberjack. (It’s for a private framework) Anyways thank you!

very well explained!
step by step
even a noob can use this by this explanation, redistribution part was quite informative
thanks for the post
regards

Hi
I have two questions:

  1. We have an app that is connecting to our server to get updates like new texts and pictures. We have a little logic in the app when we are doing payments etc, but mainly the app is just displaying data from the server. Now one of our customers wants a new GUI, but other customers wants to keep the old GUI. Is a framework for the app business logic and app database the app the right way to go?
  2. Is this article an update of this article: How to Create a Framework for iOS
  1. Frameworks are good way to go about it. In fact that’s how we’ve divided up our app. Just be careful anywhere you’re referencing the bundle, since frameworks have their own.

  2. Yes.

1 Like

Hi. Please, explain how other cocoa pod dependencies can be integrated in the framework that you have created? Thank you in advance :wink:

In the validation part, the spec didn’t pass:

→ ThreeRingControl (1.0.0)
- WARN | github_sources: Github repositories should end in .git.
- ERROR | [iOS] xcodebuild: Returned an unsuccessful exit code. You can use --verbose for more information.

Analyzed 1 podspec.

[!] The spec did not pass validation, due to 1 error and 1 warning.

What’s happening here?

Hi all! I just updated the tutorial to work with XCode 8, and Cocoapods 1.0. Hopefully this should clarify some of the build and pods errors that have been reported.

I’m getting this error when I run pod spec lint:

  • ERROR | [iOS] unknown: Encountered an unknown error (Simulator iPhone 4s is not available.) during validation.

Anybody have a clue?

I’m not sure, it might have to do with your cocoapods version or Xcode configuration. This cocoapods issue might help `pod spec lint` fails after Cocoapods 1.0 update · Issue #5320 · CocoaPods/CocoaPods · GitHub