How to automatically compile and distribute your iOS SDK as a pre-compiled xcframework

Note: This is a cross-post of the original publication on contextsdk.com.

Introduction

In this technical article we go into the depths and best practices around

  • Working efficiently on a commercial SDK in a larger team
  • How to compile and distribute your iOS SDK as a pre-compiled xcframework automatically

How to build and debug an iOS SDK?

At ContextSDK we have our whole iOS Swift codebase in a single local CocoaPod. This allows us to iterate quickly as a team, and have our SDK configuration defined in clean code in version control, instead of some plist Xcode settings.

ContextSDK.podspec

Pod::Spec.new do |s|
  s.name             = 'ContextSDK'
  s.version          = '3.2.0'
  s.summary          = 'Introducing the most intelligent way to know when and how to monetize your user'
  s.swift_version    = '5.7'
  s.homepage         = 'https://contextsdk.com'
  s.author           = { 'KrauseFx' => 'felix@contextsdk.com' }
  s.ios.deployment_target = '14.0'

  # via https://github.com/CocoaPods/cocoapods-packager/issues/216
  s.source = { :git => "file://#{File.expand_path("..", __FILE__)}" }

  s.pod_target_xcconfig = {
    "SWIFT_SERIALIZE_DEBUGGING_OPTIONS" => "NO",
    "OTHER_SWIFT_FLAGS" => "-Xfrontend -no-serialize-debugging-options",
    "BUILD_LIBRARY_FOR_DISTRIBUTION" => "YES", # for swift Library Evolution
    "SWIFT_REFLECTION_METADATA_LEVEL" => "none", # to include less metadata in the resulting binary
  }

  s.frameworks = 'AVFoundation'
  s.public_header_files = 'Classes/**/*.h'
  s.source_files = Dir['Classes/**/*.{swift}']
  s.resource_bundles = { 'ContextSDK' => ['PrivacyInfo.xcprivacy'] }

  s.test_spec 'Tests' do |test_spec|
    test_spec.source_files = [
      'Tests/*.{swift}',
      'Tests/Resources/*.{plist}'
    ]

    test_spec.dependency 'Quick', '7.2.0'
    test_spec.dependency 'Nimble', '12.2.0'
  end
end

During development, we want to easily edit our codebase, run the Demo app, and debug using Xcode. To do that, our Demo app has a simple Podfile referencing our local CocoaPod:

target 'ContextSDKDemo' do
  use_frameworks!
  pod 'ContextSDK', :path => '../ContextSDK', :testspecs => ['Tests'] 
end

Running pod install will then nicely setup your Xcode workspace, ready to run the local ContextSDK codebase:

Editing a ContextSDK source file (e.g. Context.swift) will then immediately be accessible and used by Xcode during the next compile. This makes development of SDKs extremely easy & efficient.

How to compile a CocoaPod into a static binary (xcframework)?

The requirement for commercial SDKs is often that its source code isn’t accessible to its user. To do that, you need to pre-compile your SDK into an .xcframework static binary, which can then be used by your customers.

Thanks to the excellent cocoapods-pack project, started by Dimitris by Square, it’s easily possible to compile your SDK for distribution to your customers. After installing the gem, you can use the following command:

bundle exec pod pack ../ContextSDK.podspec https://contextsdk.com --skip-validation

Now open up the folder ./zips/ContextSDK/3.2.0/ and you will see a freshly prepared ContextSDK.zip. You can’t distribute that zip file right-away, as it contains an additional subfolder called ios, which would break the distribution through CocoaPods when we tested it.

As part of our deployment pipeline, we run the following Ruby commands to remove the ios folder, and re-zip the file:

puts "Preparing ContextSDK framework for release..."

sh("rm -rf zips")
sh("bundle exec pod pack ../ContextSDK.podspec https://contextsdk.com --skip-validation") || exit(1)
sh("rm -rf files")

# Important: we need to unzip the zip file, and then zip it again without having the "ios" toplevel folder
# which will break CocoaPods support, as CococaPods only looks inside the root folder, not iOS
zip_file_path = "zips/ContextSDK/#{@version_number}/ContextSDK.zip"
sh("unzip #{zip_file_path} -d zips/current")
sh("cd zips/current/ios && zip -r ../ContextSDK.zip ./*") # Now zip it again, but without the "ios" folder
return "zips/current/ContextSDK.zip"

ContextSDK.zip is now ready for distribution. If you unzip that file, you’ll see the ContextSDK.xcframework contained directly, which is what your users will add to their Xcode project, and will be picked up by CocoaPods.

How to distribute your SDK?

Manual Installation

There are no extra steps needed: the ZIP file you created above is everything that’s needed. Now you can provide the following instructions to your users:

  1. Download the latest release: [URL to your ZIP file]
  2. Drag & Drop the ContextSDK.xcframework folder into the Xcode file list
  3. Go to your project settings, scroll down to Frameworks, Libraries, and Embedded Content, add ContextSDK.xcframework, and select Embed & Sign

Through CocoaPods

Distributing your pre-compiled .xcframework file through CocoaPods requires some extra steps.

You need a second ContextSDK.podspec file, that will be available to the public. That podspec will only point to your pre-compiled binary, instead of your source code, therefore it’s safe to distribute to the public.

Pod::Spec.new do |s|
  s.name                = 'ContextSDK'
  s.version             = '3.2.0'
  s.homepage            = 'https://contextsdk.com'
  s.documentation_url   = 'https://docs.contextsdk.com'
  s.license             = { :type => 'Commercial' }
  s.author              = { 'ContextSDK' => 'support@contextsdk.com' }
  s.summary             = 'Introducing the most intelligent way to know when and how to monetize your use'

  s.platform            = :ios, '14.0'
  s.source              = { :http => '[URL to your ZIP file]' }

  s.xcconfig            = { 'FRAMEWORK_SEARCH_PATHS' => '"$(PODS_ROOT)/ContextSDK/**"' }
  s.frameworks          = 'AVFoundation'
  s.requires_arc        = true
  s.swift_version       = '5.7'
  s.module_name         = 'ContextSDK'

  s.preserve_paths      = 'ContextSDK.xcframework'
  s.vendored_frameworks = 'ContextSDK.xcframework'
end

Make both your podspec, and your ZIP file available to the public. Once complete, you can provide the following instructions to your users:

  1. Add the following dependency to your Podfile:
    pod 'ContextSDK', podspec: '[URL to your public .podspec]'
    
  2. Run pod install

Through Swift Package Manager (SPM)

Create a new git repo (we called it context-sdk-releases), which will contain all your historic and current releases, as well as a newly created Package.swift file:

// swift-tools-version:5.4

import PackageDescription

let package = Package(
    name: "ContextSDK",
    products: [
        .library(
            name: "ContextSDK",
            targets: ["ContextSDK"]),
    ],
    dependencies: [],
    targets: [
        .binaryTarget(
            name: "ContextSDK",
            path: "releases/ContextSDK.zip"
        )
    ]
)

You can use the same zip file we’ve created with SPM as well. Additionally, you’ll need to make use of git tags for releases, so that your customers can pinpoint a specific release. You can either make this repo public, or you’ll need to manually grant read permission to everyone who wants to use SPM.

To your users, you can provide the following instructions:

  1. Add https://github.com/context-sdk/context-sdk-releases as dependency

Conclusion

As we were building out our automated SDK distribution, we noticed there aren’t a lot of guides online around how to best develop, build and distribute your SDK as a pre-compiled binary, so we hope this article helps you to get started.

If you have any questions, feel free to reach out to us on Twitter or LinkedIn, or subscribe to our newsletter on contextsdk.com.

Note: This is a cross-post of the original publication on contextsdk.com.

Tags: ios, context, sdk, swift, xcframework, compile, distribute, automation, fastlane   |   Edit on GitHub

ContextSDK - Optimize your ATT prompts

Launching AppTrackingTransparency.ai - the first, of many hyper-focused ContextSDK products, helping you increase your app’s revenue.

Apps relying on ad-revenue have struggled showing the App Tracking Transparency (ATT) prompt at the right time, reducing their likelihood of an opt-in. Large players in the market have shared that an increase of 10% ATT opt-in can increase their revenue by 5-7%.

Thanks to the new ContextSDK technology, we can significantly increase your opt-in rate, by leveraging on-device Machine Learning and the user’s real-world context to find the perfect moment to trigger the prompt. All of this, while fully preserving the user’s privacy, never using any PII, and minimal footprint of 700 KB in your app’s binary.

You only have one shot at showing the prompt, therefore, timing is crucial. We leverage the user’s real-world context, as well as your specific app’s usage patterns, to find the perfect moment to trigger the ATT prompt in your app.

You can get started using ContextSDK for optimizing your App Tracking Transparency prompt completely risk-free using just a single line of code:

At first your ATT prompt behaviour won’t change, and it’s always shown. Only once we’ve calibrated your model, we will automatically choose the perfect time to prompt the user. The integration is super easy:

  1. Integrate ContextSDK and replace ATTrackingManager with ContextManager
  2. Ship an App Store update, and ContextSDK will automatically calibrate its signals towards your app and user base
  3. Get your own custom ML Model, packaged in your personal ContextSDK Binary, ready to start optimizing your app

For pricing details, and to sign-up, check out AppTrackingTransparency.ai.

Tags: ios, context, sdk, swift, upsell, in-app, prompt, att, app, tracking, transparency   |   Edit on GitHub

ContextSDK - Angel Round, Dieter Rappold joining as CEO, first large customers

Over the last few months, a ton has happened with ContextSDK, a new developer tool to optimize apps based on the user’s current context:

Today, apps often have little logic when it comes to timing in-app communications or upsells. “Every day, billions of prompts and popups are shown at suboptimal times, resulting in annoyed users and increased churn.” said Felix Krause, co-founder of ContextSDK. “With today’s computing power, precise smartphone sensor data, combined with the latest machine learning algorithms, we can do much better than that.” Felix Krause aims to build the foundation for the next generation of mobile apps.


Angel Round

ContextSDK announces its first funding round, led by high profile Business Angels such as Peter Steinberger (founder of PSPDFKit), Johannes Moser (founder of Immerok), Michael Schuster (former Partner Speedinvest), Christopher Zemina (founder Friday Finance, GetPliant), Ionut Ciobotaru (former CEO Verve Group), Eric Seufert (Heracles Capital), Moataz Soliman (co-Founder Instabug) and others.

Dieter Rappold joining as CEO

Dieter Rappold has recently joined ContextSDK as co-founder and CEO. With more than 20 years of experience in building and scaling companies, Dieter will be responsible for the company’s growth and operations.

ContextSDK Performance

One recently onboarded customer, as a case study, showed 500 million upselling prompts, resulting in 24 million sales. With ContextSDK they experienced a remarkable +43% increase in conversion rates for new customers.

ContextSDK is an extremely lightweight SDK for iOS apps, using only 0.2% of CPU, less than a MB of memory footprint, and less than a MB added to the app’s binary size. It is fully GDPR compliant, not collecting any PII at any point.

Privacy

Recently passed laws across the world signify a clear trend towards user privacy and data protection, resulting in many previously used services to be deemed unlawful, or only offering limited capabilities.

ContextSDK was built from the ground up with privacy in mind. All processing, including the execution of machine learning models, happen on-device. ContextSDK operates without any type of PII (Personal Identifiable Information), thanks to a completely new and unique mechanism built to fully protect the user’s privacy while also helping app developers achieve their business goals.

New Website

We’ve also just launched our new ContextSDK website, now including more details on how ContextSDK works, and how it can help your business.

Interested in using ContextSDK?

As ContextSDK is a brand-new product, we carefully select the companies we want to work with. We’ve been seeing the best performance improvements for apps with a minimum of 20,000 monthly active users, as that’s where our machine learning approach really shines. If you believe your app would be a good fit, sign up for ContextSDK here.

We’re hiring

We’re hiring a Data Scientist, check out our careers page.

Full Press Release

Read the full press release on contextsdk.com

Tags: ios, context, sdk, swift, upsell, in-app   |   Edit on GitHub

ContextSDK - Introducing the most intelligent way to know how and when to monetize your user

Today, whether your app is opened when your user is taking the bus to work, in bed about to go to sleep, or when out for drinks with friends, your product experience is the same. However, apps of the future will perfectly fit into the context of their users’ environment.

As app usage has exploded over the past decade, personalization and user context are becoming increasingly important to grow and retain your userbase. ContextSDK enables you to create intelligent products that adapt to users’ preferences and needs, all while preserving the user’s privacy and battery life using only on-device processing.

ContextSDK leverages machine learning to make optimized suggestions when to upsell an in-app purchase, what type of ad and dynamic copy to display, or predict what a user is about to do in your app, and dynamically change the product flows to best fit their current situation.

Commute on the train

Alone and bored at night

In a loud bar with friends

Your users have different needs based on the context of what they are doing and where they are. Shouldn’t your app be more personalized to better serve them?


ContextSDK takes hundreds of signals and builds a highly accurate and complex model, to correlate what a user is doing and the impact it has on in-app conversion events.

ContextSDK performance

Meta has published data on how “less is more” when it comes to notifications and user prompts: Even though in the short-term, just showing something on every possible occasion will increase your chances of the user engaging, in the long-run, you are better off showing fewer prompts, only when the user is most likely to convert.

Context matters! Large tech companies are already using those techniques to optimise their apps, and now is your chance to benefit from it as well. Sign up to get started.

Tags: ios, context, sdk, swift, upsell, in-app   |   Edit on GitHub