Delegate vs DI - Similar Execution, Different Intent

Delegate vs. DI
Adarsh
iOS Engineer
|
June 16, 2025
iOS
Swift

In iOS development, we often use patterns like delegation and dependency injection (DI) to structure code and manage relationships between objects. On the surface, both involve passing an object (or a reference to one) into another object. So a natural question arises: Are these really different things, or are we just playing with words?

This article breaks down the differences and similarities, explains their roles in clean architecture, and finally answers some of the philosophical questions developers often wrestle with.

What Is a Delegate in Swift?

A delegate is a design pattern used to communicate back from one object to another, typically in a one-to-one relationship. It is used when object A wants to notify object B about certain events, or ask object B to decide how to handle a situation.

The key idea: “Hey, delegate — something happened, what should I do?” or “Hey, delegate — I did this, now you can respond.”

Example Use Case:

UITableView has a delegate that informs your controller when a row is tapped, when scrolling starts, etc. You implement methods from UITableViewDelegate to respond to these events.

What Is Dependency Injection (DI)?

Dependency injection is a design principle for providing an object with its required collaborators (aka dependencies) from the outside, rather than having it create them itself. It’s about decoupling objects to make them more modular and testable.

The key idea: “Hey, I can’t do my job without this helper. Please give it to me when I’m initialized.”

Example Use Case:

A UserService that handles networking is injected into a UserViewModel, so the view model doesn't depend on a specific networking implementation. This makes testing and swapping implementations easier.

So… Are They the Same?

On the surface, they look similar:

  • You’re passing an object reference from one class to another.
  • Both enable one object to call methods on another.
  • Both help with separation of concerns.

But their intent and responsibility are fundamentally different:

Aspect Delegate Dependency Injection Purpose Notify, report, or request decisions Provide required functionality Direction of communication Callbacks, often after an event occurs Consumer calls the dependency directly Relationship Often optional, one-to-one, event-driven Required, fixed, functional Example UITableViewDelegate Injecting a NetworkService into a class Can replace it dynamically? Yes (like assigning a new delegate) Rarely (services are generally stable)

But What If I Use a Delegate to Call an API?

You’re right to ask: “If I can ask a delegate to call an API, and I can also ask an injected service to do the same, how is it different?”

It’s not about what can be done, but about what should be done.

  • Technically, both can be used for the same task.
  • Architecturally, delegates are event-driven and should be used for notification and customization.
  • Dependencies (via DI) are utilities or helpers that are essential for performing a core task.

So while you can call an API from a delegate, doing so would likely violate the Single Responsibility Principle and make your code harder to reason about and test.

To sum it up:

Yes, both Delegates and Dependency Injection involve passing objects around. But design patterns aren’t just about mechanics — they’re about intent.

Use delegates when you want object A to notify object B about something that happened, or let B influence the behavior of A.
Use dependency injection when object A needs to use services or functionality provided by object B, and you want to keep things decoupled and testable.

Stick to their intended roles, and your architecture will stay clean, flexible, and understandable.

Frequently Asked Questions (from Developers)

1. Isn’t a delegate just another form of dependency injection?

Yes, in a very mechanical sense. You’re injecting a collaborator. But semantically and architecturally, delegation is about callbacks and notifications, not core functionality.

2. What if I use my delegate to make an API call — how is that different?

It can work, but it’s generally poor architecture. Delegates should notify or ask for advice, not perform services. Otherwise, you blur the line between control and responsibility.

3. So, is this just playing around with names?

Not really. Patterns exist to help guide design. Delegation is event-based; DI is responsibility-based. The boundary keeps architecture clean.

4. What if I really want to do things interchangeably?

You could, but over time, you’ll end up with confusing, tightly coupled, hard-to-test code. Follow the pattern that suits your intent, not just your syntax.

5. Can both patterns coexist?

Absolutely! In fact, they often do. A view controller might have a delegate to get notified about something and a service injected via DI to fetch data.


Let design patterns guide your architecture — not just by what’s possible, but by what’s intended. That’s the difference between clever code and clean code.

Recommended Posts

Figma logo on a flowchart with arrows connecting various gray interface elements on a dark background, illustrating a design process.
Figma
Design
Navigating Seamless Design: A Deep Dive into Figma User Flows
Jan 09, 2024
|
Pranesh
Man with headset working on a laptop, illustrating how Sora AI facilitates accessible video creation.
AI
Video
How Sora AI Video Generator is Making Video Creation Accessible to Everyone
Oct 04, 2024
|
Sohini

Ready to get started?

Schedule a discovery call and see how we’ve helped hundreds of SaaS companies grow!