Al crear apps iOS con Swift, tarde o temprano surge esta duda.
«¿Qué forma de inyección de dependencias debería usar?»
Empecemos por la conclusión.
Salvo que haya un motivo concreto, la inyección por constructor (init) es la opción más cercana a la correcta.
Explicaré por qué y cuándo conviene usar las otras dos opciones, basándome en experiencia real.
Tres formas de inyección: lo esencial primero
Antes de complicarnos, fijemos la base. En Swift hay tres formas principales de proporcionar dependencias.
- Inyección por constructor (init) —
initrecibe dependencias como parámetros - Inyección por propiedad —
varasignarlas después a una propiedad - Inyección por método — inyectarlas mediante un método independiente
Este es el código de la opción más recomendada: la inyección por constructor.
final class OrderService {
private let repo: MemberRepository // let garantiza la inmutabilidad
init(repo: MemberRepository) { // constructor(init) inyección
self.repo = repo
}
}
Funciona solo con la sintaxis nativa de Swift, sin bibliotecas adicionales, así que el código queda limpio.
En cambio, la inyección por propiedad es así de breve.
final class OrderService {
var repo: MemberRepository! // parece cómoda porque ocupa una sola línea…
}
A primera vista, la inyección por propiedad parece claramente más sencilla. Pero esa comodidad puede causar problemas después.
¿Por qué se desaconseja la inyección por propiedad?
Empezaré por algo que viví personalmente.
La inyección por propiedad resulta muy incómoda al hacer pruebas. Si olvidas inyectar después de crear el objeto, aparece un fallo por desempaquetado forzoso y el tipo, por sí solo, no indica qué debes proporcionar para completarlo.
Con inyección por constructor, puedes introducir directamente un mock como OrderService(repo: mockRepo) usando código Swift puro.
El segundo problema es que no puedes usar la palabra clave let.
La inyección por constructor permite declarar las propiedades como let, de modo que quedan inmutables tras la inyección.
La inyección por propiedad, en cambio, usa var, por lo que el valor puede cambiarse en cualquier momento y aumenta el riesgo de errores.
El tercer problema son las referencias circulares.
Si A referencia a B y B a A, la inyección por propiedad puede no detectarlo hasta que la app se ejecuta. El fallo aparece al entrar en esa pantalla.
La inyección por constructor revela el problema al crear el objeto (y, si el diseño está mal planteado, ni siquiera compila), por lo que puedes detectarlo mucho antes.
Tabla comparativa de un vistazo
Explicarlo con palabras puede confundir, así que lo resumí en una tabla. (Recomendación de la comunidad Swift en 2026)
| Categoría | Inyección por constructor (init) | Inyección por propiedad | Inyección por método |
|---|---|---|---|
| Inmutabilidad (let) | Posible ⭕ | No posible ❌ | No posible ❌ |
| Facilidad para probar | Alta | Baja | Media |
| Detección de referencias circulares | Inmediata al crear | Se detecta tarde | Se detecta tarde |
| Dependencia obligatoria/opcional | Adecuada para obligatorias | Distinción ambigua | Adecuada para opcionales |
| Concisión del código | Media | Muy concisa | Media |
La tendencia se ve claramente en la tabla, ¿verdad?
La inyección por constructor destaca en la mayoría de los aspectos. Por eso la documentación de bibliotecas DI como Swinject y Factory la recomienda como opción predeterminada.
Entonces, ¿cuándo se usan las otras dos formas?
No significa que debas usar siempre la inyección por constructor. Cada opción tiene su lugar.
La inyección por método funciona bien para dependencias opcionales.
Cuando el objetivo de la inyección no es obligatorio —se usa si está disponible, pero se puede prescindir de él— puedes incorporarlo con flexibilidad mediante un método como configure(with:).
La inyección por propiedad aún tiene sentido cuando no controlamos directamente la inicialización, por ejemplo, en un view controller creado mediante storyboard.
En el código normal de la aplicación, conviene evitarla siempre que sea posible.
En resumen:
- Dependencia obligatoria → inyección por constructor
- Dependencia opcional → inyección por método
- Inyección por propiedad en código general → evitar
Preguntas frecuentes
P. ¿Las bibliotecas DI como Factory facilitan la inyección por constructor?
Sí. Si registras en Swinject o Factory cómo crear las dependencias, el contenedor crea por ti los objetos que se pasan al constructor. El código se acorta y conserva ventajas como la let inmutabilidad.
P. ¿Qué ocurre si el constructor acaba teniendo demasiados parámetros?
No es un problema de la forma de inyección, sino una señal de que la clase hace demasiadas cosas. Primero, considera dividir responsabilidades entre varias clases.
P. ¿Hace falta una biblioteca DI incluso en un proyecto pequeño?
No. En un proyecto con pocas pantallas, basta con inyección por constructor usando Swift puro, pasando las dependencias directamente init.
Al principio es fácil sentirse atraído por la comodidad de la inyección por propiedad, pero al escribir pruebas y colaborar entiendes por experiencia por qué se destacan tanto las ventajas de la inyección por constructor.
Si tienes dudas, empieza con inyección por constructor. Agradecerás la decisión a medida que crezca el código.

