Skip to content

Circular dependencies

Ilya Puchka edited this page Apr 18, 2016 · 5 revisions

Circular dependency is the situation when you have two components referencing each other. Generally you should avoid that. But Dip can help you to resolve circular dependencies. For that you need to register your components with ObjectGraph scope, so that will be reused in a single object graph, and use resolveDependencies method of DefinitionOf returned by register method:

container.register(.ObjectGraph) {
    ClientImp(server: try container.resolve() as Server) as Client 
}

container.register(.ObjectGraph) { ServerImp() as Server }
    .resolveDependencies { container, server in 
        server.client = try container.resolve() as Client

In this example we have a Server that has a reference to a Client and a Client that has a reference to a Server. Client uses constructor injection to inject an instance of a Server. Then Server should use property injection to inject a Client. Otherwise we will have infinite recursion.

When you ask container to resolve a Client you will get an instance of ClientImp with reference to ServerImp which will have a reference to the same ClientImp instance.

let client = try! container.resolve() as Client
client === client.server.client

Note: don't forget about retain cycles - if you have circular dependencies one of them should be stored in a weak reference. If Client holds weak reference to Server then you will need to resolve Server first, so that it does not get released when resolve returns:

class ClientImp: Client {
  weak var server: Server
  ...
}

class ServerImp: Server {
  var client: Client
  ...
}

let client = try! container.resolve() as Client
client.server // will be nil because no one reference `Server` instance strongly before `resolve` returns

let server = try! container.resolve() as Server
server.client.server  //will be not nil, because `server` is a strong reference to `Server` instance.