Skip to content
cocoapods-subspecs-organization logo

CocoaPods - Subspecs Organization

cocoapods-subspecs-organization

Use when organizing complex CocoaPods libraries into subspecs. Covers modular architecture, dependency management between subspecs, and default subspecs patterns for better code organization and optional features.

TheBushidoCollective/han0installs199stars

SKILL.md

Full skill instructions

CocoaPods - Subspecs Organization

Organize complex libraries into modular subspecs for better maintainability and optional features.

What Are Subspecs?

Subspecs allow you to split a pod into logical modules that can be installed independently or as a group.

Benefits

  • Modularity: Separate core functionality from optional features
  • Selective Installation: Users install only what they need
  • Reduced Dependencies: Optional features don't force unnecessary dependencies
  • Better Organization: Clear separation of concerns

Basic Subspec Pattern

Pod::Spec.new do |spec|
  spec.name = 'MyLibrary'
  spec.version = '1.0.0'

  # Main spec has no source files - all in subspecs
  spec.default_subspecs = 'Core'

  # Core subspec - installed by default
  spec.subspec 'Core' do |core|
    core.source_files = 'Source/​Core/​**/​*.swift'
    core.frameworks = 'Foundation'
  end

  # Optional feature subspec
  spec.subspec 'Networking' do |networking|
    networking.source_files = 'Source/​Networking/​**/​*.swift'
    networking.dependency 'MyLibrary/​Core'  # Depends on Core
    networking.dependency 'Alamofire', '~> 5.0'
  end

  # Another optional feature
  spec.subspec 'UI' do |ui|
    ui.source_files = 'Source/​UI/​**/​*.swift'
    ui.dependency 'MyLibrary/​Core'
    ui.ios.frameworks = 'UIKit'
    ui.osx.frameworks = 'AppKit'
  end
end

Dependency Patterns

Subspec Dependencies

Pod::Spec.new do |spec|
  spec.name = 'MySDK'

  # Foundation layer
  spec.subspec 'Core' do |core|
    core.source_files = 'Source/​Core/​**/​*.swift'
  end

  # Networking depends on Core
  spec.subspec 'Networking' do |net|
    net.source_files = 'Source/​Networking/​**/​*.swift'
    net.dependency 'MySDK/​Core'
    net.dependency 'Alamofire', '~> 5.0'
  end

  # Analytics depends on Core and Networking
  spec.subspec 'Analytics' do |analytics|
    analytics.source_files = 'Source/​Analytics/​**/​*.swift'
    analytics.dependency 'MySDK/​Core'
    analytics.dependency 'MySDK/​Networking'
  end
end

External Dependencies Per Subspec

spec.subspec 'SQLite' do |sqlite|
  sqlite.source_files = 'Source/​SQLite/​**/​*.swift'
  sqlite.dependency 'MyLibrary/​Core'
  sqlite.dependency 'SQLite.swift', '~> 0.14'
  sqlite.libraries = 'sqlite3'
end

spec.subspec 'Realm' do |realm|
  realm.source_files = 'Source/​Realm/​**/​*.swift'
  realm.dependency 'MyLibrary/​Core'
  realm.dependency 'RealmSwift', '~> 10.0'
end

Default Subspecs

Single Default Subspec

Pod::Spec.new do |spec|
  spec.name = 'MyLibrary'

  # When users do: pod 'MyLibrary'
  # Only Core is installed
  spec.default_subspecs = 'Core'

  spec.subspec 'Core' do |core|
    core.source_files = 'Source/​Core/​**/​*.swift'
  end

  spec.subspec 'Extensions' do |ext|
    ext.source_files = 'Source/​Extensions/​**/​*.swift'
    ext.dependency 'MyLibrary/​Core'
  end
end

Multiple Default Subspecs

Pod::Spec.new do |spec|
  spec.name = 'MySDK'

  # When users do: pod 'MySDK'
  # Both Core and Networking are installed
  spec.default_subspecs = 'Core', 'Networking'

  spec.subspec 'Core' do |core|
    core.source_files = 'Source/​Core/​**/​*.swift'
  end

  spec.subspec 'Networking' do |net|
    net.source_files = 'Source/​Networking/​**/​*.swift'
    net.dependency 'MySDK/​Core'
  end

  spec.subspec 'Analytics' do |analytics|
    analytics.source_files = 'Source/​Analytics/​**/​*.swift'
    analytics.dependency 'MySDK/​Core'
    # Optional - not installed by default
  end
end

Platform-Specific Subspecs

Pod::Spec.new do |spec|
  spec.name = 'CrossPlatformLib'

  # Shared core
  spec.subspec 'Core' do |core|
    core.source_files = 'Source/​Core/​**/​*.swift'
    core.frameworks = 'Foundation'
  end

  # iOS-only subspec
  spec.subspec 'iOS' do |ios|
    ios.source_files = 'Source/​iOS/​**/​*.swift'
    ios.dependency 'CrossPlatformLib/​Core'
    ios.ios.deployment_target = '13.0'
    ios.ios.frameworks = 'UIKit'
  end

  # macOS-only subspec
  spec.subspec 'macOS' do |macos|
    macos.source_files = 'Source/​macOS/​**/​*.swift'
    macos.dependency 'CrossPlatformLib/​Core'
    macos.osx.deployment_target = '10.15'
    macos.osx.frameworks = 'AppKit'
  end
end

Resource Bundles in Subspecs

spec.subspec 'UI' do |ui|
  ui.source_files = 'Source/​UI/​**/​*.swift'

  # Each subspec can have its own resource bundle
  ui.resource_bundles = {
    'MyLibrary_UI' => [
      'Resources/​UI/​**/​*.{png,jpg,xcassets}',
      'Resources/​UI/​**/​*.{storyboard,xib}'
    ]
  }

  ui.dependency 'MyLibrary/​Core'
end

spec.subspec 'Themes' do |themes|
  themes.source_files = 'Source/​Themes/​**/​*.swift'

  themes.resource_bundles = {
    'MyLibrary_Themes' => ['Resources/​Themes/​**/​*']
  }

  themes.dependency 'MyLibrary/​UI'
end

Common Subspec Patterns

Core + Optional Features

Pod::Spec.new do |spec|
  spec.name = 'MyFramework'
  spec.default_subspecs = 'Core'

  # Required core functionality
  spec.subspec 'Core' do |core|
    core.source_files = 'Source/​Core/​**/​*.swift'
  end

  # Optional: JSON serialization
  spec.subspec 'JSON' do |json|
    json.source_files = 'Source/​JSON/​**/​*.swift'
    json.dependency 'MyFramework/​Core'
    json.dependency 'SwiftyJSON', '~> 5.0'
  end

  # Optional: XML support
  spec.subspec 'XML' do |xml|
    xml.source_files = 'Source/​XML/​**/​*.swift'
    xml.dependency 'MyFramework/​Core'
  end

  # Optional: Networking
  spec.subspec 'Networking' do |net|
    net.source_files = 'Source/​Networking/​**/​*.swift'
    net.dependency 'MyFramework/​Core'
    net.dependency 'Alamofire', '~> 5.0'
  end
end

Layered Architecture

Pod::Spec.new do |spec|
  spec.name = 'MySDK'

  # Layer 1: Foundation
  spec.subspec 'Foundation' do |foundation|
    foundation.source_files = 'Source/​Foundation/​**/​*.swift'
  end

  # Layer 2: Data (depends on Foundation)
  spec.subspec 'Data' do |data|
    data.source_files = 'Source/​Data/​**/​*.swift'
    data.dependency 'MySDK/​Foundation'
  end

  # Layer 3: Domain (depends on Data)
  spec.subspec 'Domain' do |domain|
    domain.source_files = 'Source/​Domain/​**/​*.swift'
    domain.dependency 'MySDK/​Data'
  end

  # Layer 4: Presentation (depends on Domain)
  spec.subspec 'Presentation' do |presentation|
    presentation.source_files = 'Source/​Presentation/​**/​*.swift'
    presentation.dependency 'MySDK/​Domain'
    presentation.ios.frameworks = 'UIKit'
  end
end

Protocol + Implementations

Pod::Spec.new do |spec|
  spec.name = 'MyStorage'

  # Protocol definitions
  spec.subspec 'Core' do |core|
    core.source_files = 'Source/​Core/​**/​*.swift'
  end

  # UserDefaults implementation
  spec.subspec 'UserDefaults' do |ud|
    ud.source_files = 'Source/​UserDefaults/​**/​*.swift'
    ud.dependency 'MyStorage/​Core'
  end

  # Keychain implementation
  spec.subspec 'Keychain' do |keychain|
    keychain.source_files = 'Source/​Keychain/​**/​*.swift'
    keychain.dependency 'MyStorage/​Core'
    keychain.dependency 'KeychainAccess', '~> 4.0'
  end

  # SQLite implementation
  spec.subspec 'SQLite' do |sqlite|
    sqlite.source_files = 'Source/​SQLite/​**/​*.swift'
    sqlite.dependency 'MyStorage/​Core'
    sqlite.libraries = 'sqlite3'
  end
end

User Installation Patterns

Installing Default Subspecs

# Installs default subspecs only
pod 'MyLibrary'

Installing Specific Subspecs

# Install only Core
pod 'MyLibrary/​Core'

# Install Core and Networking
pod 'MyLibrary/​Core'
pod 'MyLibrary/​Networking'

# Or more concisely
pod 'MyLibrary', :subspecs => ['Core', 'Networking']

Installing All Subspecs

# Install everything (not recommended - bloats dependency tree)
# No built-in way - user must list each subspec

Nested Subspecs

spec.subspec 'Networking' do |net|
  # Nested subspec: Networking/​REST
  net.subspec 'REST' do |rest|
    rest.source_files = 'Source/​Networking/​REST/​**/​*.swift'
    rest.dependency 'MyLibrary/​Core'
  end

  # Nested subspec: Networking/​GraphQL
  net.subspec 'GraphQL' do |graphql|
    graphql.source_files = 'Source/​Networking/​GraphQL/​**/​*.swift'
    graphql.dependency 'MyLibrary/​Core'
    graphql.dependency 'Apollo', '~> 1.0'
  end
end

# Users install with:
# pod 'MyLibrary/​Networking/​REST'
# pod 'MyLibrary/​Networking/​GraphQL'

Best Practices

Directory Structure

MyLibrary/
├── MyLibrary.podspec
├── Source/
│   ├── Core/           # Core subspec
│   ├── Networking/     # Networking subspec
│   ├── UI/            # UI subspec
│   └── Analytics/     # Analytics subspec
├── Resources/
│   ├── Core/
│   ├── UI/
│   └── Analytics/
└── Tests/
    ├── CoreTests/
    ├── NetworkingTests/
    └── UITests/

Naming Conventions

# Use clear, descriptive names
spec.subspec 'Networking'  # Good
spec.subspec 'Net'        # Too abbreviated

# Group related functionality
spec.subspec 'UI'
spec.subspec 'UIComponents'
spec.subspec 'UIExtensions'

# Platform suffixes when needed
spec.subspec 'iOS'
spec.subspec 'macOS'

Dependency Guidelines

# Keep dependency chains shallow
spec.subspec 'A' do |a|
  a.dependency 'MyLib/​Core'  # 1 level - Good
end

spec.subspec 'B' do |b|
  b.dependency 'MyLib/​A'  # 2 levels - OK
end

spec.subspec 'C' do |c|
  c.dependency 'MyLib/​B'  # 3 levels - Consider flattening
end

Anti-Patterns

Don't

❌ Create too many small subspecs

# Over-granular
spec.subspec 'StringExtensions'
spec.subspec 'ArrayExtensions'
spec.subspec 'DictionaryExtensions'
# Better: Group as 'Extensions'

❌ Circular dependencies

spec.subspec 'A' do |a|
  a.dependency 'MyLib/​B'
end

spec.subspec 'B' do |b|
  b.dependency 'MyLib/​A'  # CIRCULAR - Will fail
end

❌ Duplicate source files

spec.subspec 'Core' do |core|
  core.source_files = 'Source/​**/​*.swift'  # Includes everything
end

spec.subspec 'Utils' do |utils|
  utils.source_files = 'Source/​Utils/​**/​*.swift'  # DUPLICATE
end

Do

✅ Group related functionality

spec.subspec 'Extensions' do |ext|
  ext.source_files = 'Source/​Extensions/​**/​*.swift'
end

✅ Use clear dependency hierarchy

spec.subspec 'A' do |a|
  a.dependency 'MyLib/​Core'
end

spec.subspec 'B' do |b|
  b.dependency 'MyLib/​Core'  # Both depend on Core - Good
end

✅ Keep source files separate

spec.subspec 'Core' do |core|
  core.source_files = 'Source/​Core/​**/​*.swift'
end

spec.subspec 'Utils' do |utils|
  utils.source_files = 'Source/​Utils/​**/​*.swift'
end

Testing Subspecs

# Lint specific subspec
pod lib lint --include-podspecs=*.podspec

# Test specific subspec in example project
cd Example
pod install
# Then build/​run in Xcode

Related Skills

  • cocoapods-podspec-fundamentals
  • cocoapods-test-specs
  • cocoapods-publishing-workflow

More skills from TheBushidoCollective

typescript-utility-types logo
TheBushidoCollective/han

typescript-utility-types

Use when typeScript utility types, mapped types, and advanced type manipulation. Use when creating flexible, type-safe TypeScript code.

199 0
View
shell-portability logo
TheBushidoCollective/han

shell-portability

Use when writing shell scripts that need to run across different systems, shells, or environments. Covers POSIX compatibility and platform differences.

199 0
View
tailwind-performance logo
TheBushidoCollective/han

tailwind-performance

Use when optimizing Tailwind CSS for production, reducing bundle size, and improving performance. Covers PurgeCSS, JIT mode, and build optimization.

199 0
View
figma-generate-component logo
TheBushidoCollective/han

figma-generate-component

Generate production-ready code from a Figma component or frame using the Figma MCP server

199 0
View
dialyzer-integration logo
TheBushidoCollective/han

dialyzer-integration

Use when integrating Dialyzer into development workflows and CI/CD pipelines for Erlang/Elixir projects.

199 0
View
rubocop-configuration logo
TheBushidoCollective/han

rubocop-configuration

Use when ruboCop configuration including YAML config, departments, inheritance, and customization.

199 0
View
elixir-otp-patterns logo
TheBushidoCollective/han

elixir-otp-patterns

Use when Elixir OTP patterns including GenServer, Supervisor, Agent, and Task. Use when building concurrent, fault-tolerant Elixir applications.

199 0
View
ameba-custom-rules logo
TheBushidoCollective/han

ameba-custom-rules

Use when creating custom Ameba rules for Crystal code analysis including rule development, AST traversal, issue reporting, and rule testing.

199 0
View
Swift Optionals Patterns logo
TheBushidoCollective/han

Swift Optionals Patterns

Use when swift's optional handling patterns including optional binding, chaining, nil coalescing, and modern approaches to safely working with optional values while avoiding common pitfalls and force unwrapping.

199 0
View
code-annotation-patterns logo
TheBushidoCollective/han

code-annotation-patterns

Use when annotating code with structured metadata, tags, and markers for AI-assisted development workflows. Covers annotation formats, semantic tags, and integration with development tools.

199 0
View
Scala Collections logo
TheBushidoCollective/han

Scala Collections

Use when scala collections including immutable/mutable variants, List, Vector, Set, Map operations, collection transformations, lazy evaluation with views, parallel collections, and custom collection builders for efficient data processing.

199 0
View
reactflow-custom-nodes logo
TheBushidoCollective/han

reactflow-custom-nodes

Use when creating custom React Flow nodes, edges, and handles. Covers custom node components, resizable nodes, toolbars, and advanced customization.

199 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View