Hide implementation of swift framework when distributing

In this article, I will demonstrate how to create a Swift NiceLogger framework and push to Cocoapods without sharing source code.

You can download the final project from NiceLogger

1. Create a Swift framework

1.1 Create a new framework project


Product Name NiceLogger, Set language to Swift

1.2 Create a new file NiceLogger.swift


Copy the code from Here into NiceLogger.swift and save it.

1.3 Build to generate framework

Now build it and you will find the colour of the framework name turns to black, which means the framework has been generated.

1.4 Create Zip Archive

Right click the NiceLogger.framework, select Show in Finder, copy the NiceLogger.framework and MIT License to the NiceLogger home folder:

1.5 Create a Zip Archive

Archive them inside a .zip, upload it to your server, and link to it using the s.source parameter in the .podspec file.

Create the NiceLogger.zip file by running the following command in your project directory:

zip -r NiceLogger.zip LICENSE NiceLogger.framework  

You can upload the NiceLogger.zip file to your server, in a path similar to the following:

https://s3.amazonaws.com/elasticbeanstalk-us-east-1-564874457370/NiceLogger.zip

You can also create a GitHub repository and push the .zip file to it.

Once you upload the .zip, link it in the s.source parameter of the .podspec file.

  s.source            = { :http => 'https://s3.amazonaws.com/elasticbeanstalk-us-east-1-564874457370/NiceLogger.zip' }

2. Create Cocoapod repo

2.1 Create .podspec

Create a NiceLogger.podspec file in your project directory which will contain information about the CocoaPod you are publishing, for instance name, version, sources, and more.

pod spec create NiceLogger

To learn more about Podspec attributes, see http://docs.cocoapods.org/specification.html
To understand how to work with Podspecs in the CocoaPods, see https://github.com/CocoaPods/Specs/

for example:


Pod::Spec.new do |s|

  s.name         = "NiceLogger"
  s.version      = "0.0.1"
  s.summary      = "A nice logger tool in Swift."
  s.description  = <<-DESC
  A nice logger tool in Swift. Cheers
                   DESC

  s.homepage     = "https://github.com/zhihuitang"
  s.license      = { :type => "MIT", :file => "license" }
  s.author             = { "Zhihui Tang" => "crafttang@gmail.com" }
  s.ios.deployment_target = '8.0'
  s.ios.vendored_frameworks = 'NiceLogger.framework'
  s.source            = { :http => 'https://s3.amazonaws.com/elasticbeanstalk-us-east-1-564874457370/NiceLogger.zip' }
  s.exclude_files = "Classes/Exclude"

end

2.2 Ensure this is a valid .podspec

pod spec lint --verbose

If everything is working, you would see the following output:

......

** BUILD SUCCEEDED **

   Testing with xcodebuild.
 -> NiceLogger (0.0.1)
    - NOTE  | [iOS] xcodebuild:  ld: warning: ignoring file NiceLogger/NiceLogger.framework/NiceLogger, file was built for x86_64 which is not the architecture being linked (i386): NiceLogger/NiceLogger.framework/NiceLogger

Analyzed 1 podspec.

NiceLogger.podspec passed validation.

2.3. Register a Trunk Account

In order to publish your .podspec file to the CocoaPods repository, first you must register an account with the CocoaPods Trunk.

The CocoaPods Trunk is an authentication and CocoaPods API service. For publishing new or update library to CocoaPods for public release, you will need to be registered with the Trunk and have a valid Trunk session on your current device.

Register an account by running the following, entering your full name and e-mail address:

pod trunk register you@email.com 'Full Name'  

Now, check your e-mail. There will be a confirmation link. Click it.

Now your Trunk account is activated and you can publish your CocoaPod!

2.4. Publish the Pod

Run the following command in the same directory as the .podspec to publish it to the CocoaPods repository:

pod trunk push NiceLogger.podspec  

The CLI will validate your .podspec and attempt to install the CocoaPod by downloading the source .zip and validating its contents. If works, you have just published your first universal binary CocoaPod!

If everything works, you would find the following output:


--------------------------------------------------------------------------------
 🎉  Congrats

 🚀  NiceLogger (0.0.1) successfully published
 📅  October 14th, 23:14
 🌎  https://cocoapods.org/pods/NiceLogger
 👍  Tell your friends!
--------------------------------------------------------------------------------

3. Create a Demo to verify the framework

3.1 Create a demo project

3.2 Init cocopods

pod init

Add dependency to Podfile

target 'Demo' do
  use_frameworks!
  pod 'NiceLogger'

  # Pods for Demo

  target 'DemoTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'DemoUITests' do
    inherit! :search_paths
    # Pods for testing
  end

end

3.3 install pod dependency

In the demo project home directory, run

pod install

yeah… we got it……, wait……

[!] Unable to find a specification for `NiceLogger`

In that case please fix it by:

pod repo update

Then run pod install again

pod install

if you are lucky again, you probably get following output:

$ pod install
Analyzing dependencies
Downloading dependencies
Installing NiceLogger (0.0.1)
Generating Pods project
Integrating client project

[!] Please close any current Xcode sessions and use `Test.xcworkspace` for this project from now on.
Sending stats
Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.

3.4 Code with NiceLogger

Navigate to the demo project, double the Demo.xcworkspace to open the demo project. You would see the source code the framework is invisible in Pods.

Now add code to verify the framework works.
Add dependency:

import NiceLogger

Add Code to viewDidLoad():

NiceLogger.d("hehe, viewDidLoad")

3.5 Run the demo project

You would find the log as follows:

2017-10-14T21:26:46.796Z [ViewController.swift#viewDidLoad()#16]-D: hehe, viewDidLoad

Thanks

Many thanks to MR. Elad Nava, I borrowed some words form his blog:
https://eladnava.com/publish-a-universal-binary-ios-framework-in-swift-using-cocoapods/

About Tang

A mobile developer, work in Stockholm, Sweden
This entry was posted in iOS, Mobile and tagged , . Bookmark the permalink.

7 Responses to Hide implementation of swift framework when distributing

  1. Mandar Joshi says:

    Hi I am getting following errors.

    WARN | summary: The summary is not meaningful.
    – ERROR | File Patterns: The NiceLogger (0.0.1) spec is empty (no source files, resources, resource_bundles, preserve paths, vendored_libraries, vendored_frameworks, dependencies, nor subspecs).
    – ERROR | [OSX] unknown: Encountered an unknown error (The `NiceLogger` pod failed to validate due to 1 error:

    Also can you please explain more how source code is hidden?

    Like

    • Tang says:

      Hi Mandar,

      The source code is hidden because only the zip file is public. When pods user run “pod install”, the NiceLogger.zip is downloaded, not the source code.

      Regarding your error, could you please give more details when did you get this error? when “pod spec lint”?

      BTW, I updated the s.source today. It works well on my local.

      Like

  2. Mandar Joshi says:

    If I uncomment default line
    s.source_files = “Classes”, “Classes/**/*.{h,m}”

    Then I get following error

    WARN | summary: The summary is not meaningful.
    – ERROR | file patterns: The `source_files` pattern did not match any file.

    Like

  3. Amine says:

    HI, thank you for this tutorial.
    But Really need to know how can we expose our classes and methods in the framework.In the niceLogger-swift.h we do not see classes methods and var declarations …

    Like

  4. Shakeer says:

    Hi,

    Good tutorial! I was able to hide my code. I have a question regarding source url.
    Can the ‘s.source’ url in a podspec be replaced by a private url ?

    Like

  5. Cloy Monis says:

    Hi

    It was a great example. I am facing the following issues

    ERROR | [iOS] file patterns: The `source_files` pattern did not match any file.

    Like

  6. Cloy Monis says:

    Hi I was able to find out the problem…….I had to comment out source_files and include vendors frameworks…..

    Like

Leave a comment