Resource Bundling in CocoaPods: Decoded 🧐

Ajay Kumar
5 min readJan 24, 2024
Photo by Rodrigo Flores on Unsplash

Ever wondered how seamlessly integrating third-party libraries into your iOS projects could become a reality? CocoaPods, being one of the ways to simplify the process and enhance your apps with external functionality, takes the spotlight. As we delve deeper into the intricacies of iOS development, a fundamental question arises: how are resources handled and bundled within the realm of CocoaPods? In this exploration, we unravel the mysteries of resource bundling, providing insights that empower iOS developers to efficiently manage assets in their Swift projects.

Cocoapod Creation

To initiate the creation of a CocoaPod, head over to your terminal and use the following command:

pod lib create <pod_name>

After executing this command, CocoaPods will guide you through a series of prompts to set up your library. Once your CocoaPod is created, let’s take a closer look at the folder structure and understand the role of the podspec.json file.

Folder Structure

The generated folder structure for your CocoaPod will include various files and directories, with key components being:

  • <pod_name>: This directory encompasses both assets and classes, serving as the core of your pod.
  • Example: Within this directory, an Xcode project is provided, allowing you to build, run, and test the CocoaPod you’ve created.
  • <pod_name>.podspec: This file acts as the specification, detailing the metadata and configuration of your CocoaPod. This is how your .podspec looks like:
Pod::Spec.new do |s|
s.name = 'Resource-Bundling-Cocoapods'
s.version = '0.0.1'
s.summary = '<TBA>'


s.homepage = 'https://github.com/ajkmr7/Resource-Bundling-Cocoapods'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'Ajay Kumar' => 'ajayyasodha@gmail.com' }
s.source = { :git => 'https://github.com/ajkmr7/Resource-Bundling-Cocoapods.git', :tag => s.version.to_s }

s.ios.deployment_target = '11.0'

s.source_files = 'Resource-Bundling-Cocoapods/Classes/**/*'

# s.resource_bundles = {
# 'Resource-Bundling-Cocoapods' => ['Resource-Bundling-Cocoapods/Assets/**']
# }

end

Core of Cocoapods

Before delving into the specifics of managing resources, let’s explore the foundational elements that enrich your CocoaPod — a fusion of essential assets and well-organized classes.

  • Assets: This includes images, colors, fonts, localizable strings, and JSON files, enhancing the diversity of your library’s capabilities.
  • Classes: A collection of classes, featuring parsers for assets, helper classes, and a couple of view controllers.
  • Unit Tests: A class to test the sample JSON.
Core of Cocoapods

The folders highlighted in blue are the Assets, while the remaining ones contain the files added as part of the Classes folder.

Ways of exposing resources inside cocoapod

When incorporating resources such as color assets, image assets, fonts, localizable strings, and JSON files into a CocoaPod, two primary methods within the PodSpec file govern their accessibility:

s.resources

When utilizing s.resources, you are essentially informing CocoaPods about the specific files your library will load at runtime. For dynamic frameworks, these files are seamlessly copied to the resource folder path of that framework.

s.resources = ['Resource-Bundling-Cocoapods/Assets/**']

Note: The decision of whether a Pod is built as a dynamic framework or a static library is not determined by the PodSpec but rather by the Podfile of the integrating application, Example App in our case.

s.resource_bundles

However, in the case of static libraries, these files are copied to the resource folder of the main application bundle (.app).

s.resource_bundles = {
'Custom-Pod-Resources' => ['Resource-Bundling-Cocoapods/Assets/**']
}

Ensure that the bundle name, Custom-Pod-Resources in this case, is not the same as the pod name itself. This precaution is necessary because there will be an .exe file of the pod in the same path as the bundle, generated upon installing the pod and successfully running the app.

Ways of exposing Classes & UnitTests inside cocoapod:

s.source_files = 'Resource-Bundling-Cocoapods/Classes/**/*'
.
.
.
s.test_spec 'UnitTests' do |test_spec|
test_spec.source_files = 'Resource-Bundling-Cocoapods/UnitTests/**'
end

Any class requiring access to assets within the resource bundle should seek the relevant bundle for consumption, avoiding reliance on the default .main bundle.

ResourceBundle.swift

import Foundation

final class ResourceBundle {
static let bundle: Bundle = {
let myBundle = Bundle(for: ResourceBundle.self)

guard let bundleURL = myBundle.url(
forResource: "Custom-Pod-Resources", withExtension: "bundle"
)
else { fatalError("Custom-Pod-Resources.bundle not found!") }

guard let bundle = Bundle(url: bundleURL)
else { fatalError("Cannot access Custom-Pod-Resources.bundle!") }

return bundle
}()
}

To execute UnitTests, ensure you incorporate the following modification into the Podfile of the Example project.

use_frameworks!

platform :ios, '10.0'

target 'Resource-Bundling-Cocoapods_Example' do
pod 'Resource-Bundling-Cocoapods', :path => '../', :testspecs => ['UnitTests']

target 'Resource-Bundling-Cocoapods_Tests' do
inherit! :search_paths
end
end

After including all the necessary assets and classes, execute pod install in terminal and launch the Example app.

Viewing Contents of Resource Bundle:

To inspect the contents of the resource bundle, follow these steps:

1. Run the app and navigate to DerivedData -> <pod_name*> -> Build -> Products -> Debug-iphonesimulator -> <app_name>.app

2. Right-click on the app and select Show Package Contents

3. Then navigate to Frameworks -> <pod_name>.framework -> <resource_bundles_name>.bundle

4. Once again, right-click on the bundle and select Show Package Contents

Resource Bundle Contents

Make use of tools such as Asset Catalog Tinker to inspect and optimize the contents of .car files.

Key Insight:

Avoid using both s.resources and s.resource_bundles simultaneously for accessing resources. This practice can lead to asset duplication and a subsequent increase in the .app size.

Inefficient way of exposing resources

Remember, the choice between s.resources and s.resource_bundles depends on the nature of your library, and careful consideration ensures optimal resource utilization.

Link to Github Repo — https://github.com/ajkmr7/Resource-Bundling-Cocoapods

Happy coding!!!✌️

--

--