# Share Extensions in Practice – Part 1: When Duplication Beats Shared Frameworks

Table of Contents

This is part 1 of a 4-part series on building robust iOS Share Extensions:

  • Part 1: API Architecture (this article) - Pragmatic duplication vs. shared frameworks
  • Part 2: Secure Keychain Sharing - Authentication tokens and sensitive data
  • Part 3: App Groups & Core Data - Shared storage and synchronization (coming soon)
  • Part 4: SwiftUI Integration - Modern UI with hosting controllers (coming soon)

When your iOS app needs to share content, Share Extensions seem like the perfect solution. They let users share directly from other apps without switching contexts. But there’s a catch: how do you connect your extension to your existing API infrastructure?

The obvious answer is “just share the API code between targets.” Most developers instinctively reach for this approach, thinking it’ll save time and reduce duplication. But here’s where things get interesting: when it comes to Share Extensions, the obvious solution often creates more problems than it solves.

Here’s why: Extensions and main apps run in completely separate processes with no shared sandbox. Every piece of shared code must go through explicit mechanisms like App Groups or Keychain. This architectural reality makes deliberate code duplication often smarter than building elaborate shared frameworks.

This prevents common build/runtime gotchas:

  • Memory pressure: Extensions only get ~120MB RAM, shared frameworks are expensive
  • Launch time: Every extra library slows down extension startup
  • Symbol conflicts: Different versions of the same library in both targets
  • iOS updates: Extension APIs are more restrictive than app APIs

The key is deciding upfront which few classes really need to go into the extension target and what stays out.

The pragmatic approachLink to heading

Instead of building a complex framework from day one, let’s be pragmatic: We copy the few necessary API components directly into the extension. This is deliberate code duplication and brings crucial benefits:

  • Fast builds: The extension compiles only the minimum
  • Clear boundaries: No accidental dependencies to the main app
  • Easy maintenance: Changes in the main app don’t break the extension

The downsides: Code needs to be maintained in two places. Changes must be kept in sync. But that’s a conscious tradeoff for stability and performance.

Planning target structureLink to heading

Before you start implementing, get an overview of the components you need:

[CODE_PLACEHOLDER: Target Structure Example]
// Example of target organization
// - MainApp Target
// - ShareExtension Target
// - Shared API classes (duplicated)

Decision matrix: Duplicate vs. ShareLink to heading

Use this heuristic for each class:

Duplicate when:

  • Less than 100 lines of code
  • No external dependencies
  • Changes rarely (< 1x per month)
  • Simple data types (String, Int, Bool)

Share when:

  • Complex business logic (> 500 lines)
  • Many dependencies (> 3 other classes)
  • Changes frequently (> 1x per week)
  • Database/persistence layer

Copy minimal APILink to heading

The extension usually needs just 2-3 simple classes. No protocols, no abstractions:

[CODE_PLACEHOLDER: Simple API Classes]
// - ShareAPIClient (HTTP calls)
// - AuthToken (token handling)
// - ShareRequest (request model)

Watch out for dependency chainsLink to heading

What starts as sharing one simple model class can quickly become a nightmare. User.swift needs Address.swift needs Country.swift needs Localization.swift. Suddenly you’re pulling in 10+ classes.

Better approach: Create simplified extension-only models with just the essential properties. Instead of sharing complex models, define lightweight versions tailored for the extension’s needs.

Testing & debuggingLink to heading

Test your extension API separately from the main app. For debugging, remember that extensions run in separate processes:

1. Run extension
2. Xcode: Debug → Attach to Process
3. Select "YourApp ShareExtension"
4. Debug normally

With this simple steps, you can effectively debug your Share Extension.

ConclusionLink to heading

With Share Extensions, less is more. Deliberately copy the few API classes you need instead of building a complex framework. This keeps the extension fast, stable, and maintainable. A shared package is always possible later, but not necessary.

We now have an idea of the minimal API, but it usually needs an auth token or similar credentials. In the next part, we’ll look at how to securely share authentication tokens between app and extension using Keychain Access Groups.


This “Share Extensions in Practice” series shows you step by step how to develop stable, secure, and user-friendly Share Extensions for iOS.

My avatar

Thanks for reading my blog post! Feel free to check out my other posts or contact me via the social links in the footer.


More Posts