简体   繁体   中英

Extension of a protocol where the associatedType is class?

I tried something like this:

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

protocol MyProtocol {
    associatedtype Model: MyModelProtocol

    func changeModel(_ model: Model)
}

extension MyProtocol where Model: AnyObject {
}

The compiler goes happy. However, inside this extension the compiler still isn't sure if Model is class or struct. Example:

extension MyProtocol where Model: AnyObject {
    func changeModel(_ model: Model) {
        model.name = "changed"
    }
}

Thus, I get the error: "Cannot assign to property: 'model' is a 'let' constant"

How can I tell the compiler that in that protocol extension the associated type will always be a class?

Btw, this is just a short example. I know I could use an inout parameter in this case, but it doesn't work for me because I want to change the object inside of an async callback like so:

func changeModel(_ model: inout Model, completion: @escaping () -> Void) {
        Api.shared.doRandomAsyncStuff() { (_) in
            model.name = "changed"
            completion()
        }
    }

And trying to do this leads me to the error: "Escaping closures can only capture inout parameters explicitly by value".

You could just an add intermediate assignment to a var. For a class/reference type, this would have the same effect as setting a property on the original reference. For a struct type it would make a copy, which wouldn't work, but should be avoided by the constraint on the extension.

func changeModel(_ model: Model, completion: @escaping () -> Void) {
    var modelRef = model
    Api.shared.doRandomAsyncStuff() { (_) in             
        modelRef.name = "changed"
        completion()
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM