Skip to content

Latest commit

 

History

History
96 lines (71 loc) · 2.82 KB

Misc.md

File metadata and controls

96 lines (71 loc) · 2.82 KB

Misc

Value Types

Swift 2 has introduced Protocol Extensions, which reinforces Protocol Oriented Programming and usage of value types. Swinject can handle not only a reference type but also a value type as a component created by a factory.

Here you have Turtle struct implementing Animal protocol.

protocol Animal {
    var name: String { get set }
}

struct Turtle: Animal {
    var name: String
}

The struct instance can be registered and resolved as below.

let container = Container()
container.register(Animal.self) { _ in Turtle(name: "Ninja") }

var turtle1 = container.resolve(Animal.self)!
print(turtle1.name) // prints "Ninja"

Because turtle1 is actually a struct instance although its type is inferred as protocol Animal there, assigning it to a new parameter creates a new instance.

var turtle2 = turtle1
turtle2.name = "Samurai"
print(turtle2.name) // prints "Samurai"
print(turtle1.name) // prints "Ninja"

Self-registration (Self-binding)

In Swinject or other DI frameworks, a service type can not only be a protocol but also a concrete or abstract classes. A special case is when the service type and component type are identical. This case is called self-registration or self-binding. Here is an example of self-binding with Swinject:

let container = Container()
container.register(Animal.self) { _ in Cat(name: "Mimi") }
container.register(PetOwner.self) { r in
    PetOwner(name: "Selfie", pet: r.resolve(Animal.self)!)
}

Then a PetOwner service is resolved as itself:

let owner = container.resolve(PetOwner.self)!
print(owner.name) // prints "Selfie"
print(owner.pet.name) // prints "Mimi"

Where the protocols and classes are:

protocol Animal {
    var name: String { get set }
}

class Cat: Animal {
    var name: String

    init(name: String) {
        self.name = name
    }
}

class PetOwner {
    let name: String
    let pet: Animal

    init(name: String, pet: Animal) {
        self.name = name
        self.pet = pet
    }
}

Resolution failure logging

When resolve method fails, Swinject will log information about expected and available registrations to make DI debugging easier. This feature can be disabled / customized by modifying Container.loggingFunction variable, e.g.:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    Container.loggingFunction = nil // disable logging
    ...
}

Next page: Container Hierarchy

Table of Contents