1

I wanted to develop an application which uses repository patterns using core data and realm. I want to resolve protocol according to my needs. Purpose is to inject a generic core data repository / realm repository protocol in the assembly.

Problem occurs on this line saying Protocol 'SleepRepositoryProtocol' can only be used as a generic constraint because it has Self or associated type requirements

func assemble(container: Container) {
    container.register(SleepRepositoryProtocol.self) { r in
        CoreDataSleepRepository(persistentContainer:r.resolve(NSPersistentContainer.self)!)
        }.inObjectScope(.container)
}

I am unable to inject sleep repository protocol because of using generic (associated type) properties. How can I solve this problem?

Additionally,thank you very much for your response. It really helped me a lot. I have one more issue with this.

var repository: SleepRepositoryProtocol

var items: [SleepEntity]?

private let assembler: Assembler

init(assembler: Assembler) {
    self.assembler = assembler
    
    repository = assembler.resolver.resolve(SleepRepositoryProtocol.self)!
}

This gives me error "Protocol 'SleepRepositoryProtocol' can only be used as a generic constraint because it has Self or associated type requirements" and I don't know how to resolve my SleepRepositoryProtocol.

1
  • I never used swinject, but this error means that you cannot instantiate a type using a protocol with associated types. Instead, instantiate the specific type conforming to it. Commented May 1, 2021 at 13:16

1 Answer 1

1

This error is a classic:

    container.register(SleepRepositoryProtocol.self) { r in

is forbidden because SleepRepositoryProtocol is a Protocol with Associated Type.

what you would need is for the assemble(container:) method to be generic and declared this way for example:

func assemble<Repository: SleepRepositoryProtocol>(container: Container, ofType type:Repository) {

but since it's part of Swinject's Assembly Protocol it is not an option and you need to find another place to put the Generic Type Constraint.

In your case it can be the enclosing type eg.:

class MyClass<Repository: SleepRepositoryProtocol>: Assembly {
    func assemble(container: Container) {
        container.register(Repository.self) { r in
          CoreDataSleepRepository(persistentContainer:r.resolve(NSPersistentContainer.self)!)
        }
        .inObjectScope(.container)
    }
}

Edit

you cannot just write :

var repository: SleepRepositoryProtocol

Once you add associatedtype in you protocol you can never use it like a normal type, only as a Generic Type Constraint

So if I update MyClass with your other properties:

class MyClass<Repository: SleepRepositoryProtocol>: Assembly {
    var repository: Repository

    var items: [SleepEntity]?

    private let assembler: Assembler

    init(assembler: Assembler) {
        self.assembler = assembler
        
        repository = assembler.resolver.resolve(Repository.self)!
    }

    func assemble(container: Container) {
        container.register(Repository.self) { r in
          CoreDataSleepRepository(persistentContainer:r.resolve(NSPersistentContainer.self)!)
        }
        .inObjectScope(.container)
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you very much for your response. It really helped me a lot. I have one more issue with this. This gives me error and I don't know how to resolve my SleepRepositoryProtocol. var repository: RepositoryProtocol var items: [SleepEntity]? private let assembler: Assembler init(assembler: Assembler) { self.assembler = assembler repository = assembler.resolver.resolve(RepositoryProtocol.self)! }.
hard to read in a comment. you should edit your question or even better start another one
thank you so much for your response. I have updated my sleep repository and didn't use generic on it. That solved my problem and injection worked really well.
Great. I'd say as a rule you should upvote useful answers and accept the one that provide you with the best solution ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.